Predicado de encadeamento numérico


27

Problema:

Sua tarefa é decidir se, em uma sequência de números, cada número contém pelo menos um dos dígitos do número que o precedeu.

Por exemplo, o seguinte deve retornar verdade:

[1, 12, 203, 0, 30]
             ^   ^ Contains a 0
        ^ Contains a 2
    ^ Contains a 1

O seguinte deve retornar falsey:

[1, 32, 23, 34]
    ^ Doesn't contain a 1, therefore false

Seu envio pode ser uma função ou um programa completo.

Entrada:

A entrada pode ser qualquer tipo razoável de sequência. Uma matriz de números, uma matriz de cadeias, uma cadeia de números delimitada, etc.

Porém, a ordem é importante, portanto, qualquer estrutura que você escolher aceitar como entrada obviamente deve ter uma ordem definida.

A entrada pode ser obtida via stdin ou como argumento.

Você pode assumir:

  • todos os números serão inteiros não negativos

  • entrada sempre conterá pelo menos 2 números

  • os números de entrada não começarão com um 0

Saída:

A saída será um valor verdadeiro ou falso (conforme definido pelo seu idioma), representando se a especificação acima foi ou não atendida.

Os valores de verdade / falsey não precisam ser consistentes entre os testes.

Pode ser enviado para o stdout ou retornado.

Casos de teste:

True cases:
[1, 1, 1, 11, 111, 11, 1]
[12, 23, 34, 45, 56]
[65, 54, 43, 32, 21]
[123, 29, 9, 59, 55, 52, 2017, 2]
[1234567890, 19, 95, 5012, 23]

False cases:
[1, 2, 3, 4, 5, 1, 11] (2 doesn't contain a 1)
[12, 23, 33, 45] (45 doesn't contain a 3)
[98, 87, 76, 11, 12, 23] (11 doesn't contain a 7 or 6)

Isso é código-golfe, então o menor número de bytes vence.

Respostas:


7

Geléia , 5 4 bytes

f2\Ạ

Entrada é uma matriz de seqüências de caracteres.

Experimente online!

Como funciona

f2\Ạ  Main link. Argument: A (array of strings)

 2\   Pairwise reduce by:
f       Filter, yielding all chars in the left string that appear in the right one.
   Ạ  All; yield 1 if all strings are non-empty, 0 if not.


12

Retina , 25 20 bytes

(.).*¶(?=.*\1)

^.+$

Experimente online!

Sempre que encontramos um dígito que também ocorre no próximo número, removemos o separador entre esses números (junto com os dígitos do número anterior, começando pelo compartilhado, mas isso é irrelevante). A entrada é válida, se todos os separadores tiverem sido removidos no processo, que verificamos, assegurando que a string possa corresponder como uma única linha.


11

Braquilog , 9 bytes

{⊇ᵐ=∧?t}ˡ

Experimente online!

Observe que isso não funciona apenas com uma lista de números inteiros, mas também com uma lista de cadeias ou uma lista de listas.

Explicação

{      }ˡ       Left fold on the input:
 ⊇ᵐ=              It is possible to find a number which is a subset of both input numbers
    ∧             (and)
     ?t           The output is the second number (to continue the fold)

2
Isso é legal. Parece ... declarativo? Lê como se você estivesse apenas dizendo ao idioma a especificação.
Carcigenicate

3
@Cachigenicate Brachylog é realmente declarativo, é baseado na linguagem de programação lógica declarativa Prolog .
Fatalize 15/03

2
Prologs na minha (cada vez mais) longa lista de idiomas para aprender quando eu tiver tempo livre ilimitado. Existem muitos idiomas legais!
Carcigenicate

8

JavaScript (ES6), 47 44 * 43 bytes

Guardou um byte graças a @Neil

x=>x.every(y=>y.match(`[${p}]`,p=y),p=1/19)

Recebe entrada como uma lista de seqüências de caracteres.

Snippet de teste

* ( riscado 44 ainda é regular 44 )


Não `[${p}]`funciona?
21417 Neil

@ Neil Não é para o primeiro item de cada matriz.
ETHproductions

Ah, vejo que você encontrou uma solução alternativa. Eu tinha chegado até onde a=>a.reduce((l,r)=>`${l}`.match(`[${r}]`)&&r)(que também funciona para entrada numérica).
Neil

Talvez você possa remover o p&&se você definir p=1/19?
Neil

@ Neil I, uh ... bem ... Isso é genial, obrigado :-)
ETHproductions 15/17

6

05AB1E , 10 bytes

ü‚vy`Så1åP

Experimente online! ou como um conjunto de testes

Explicação

ü‚          # map pairing over each pair in input
  v         # for each pair
   y`       # push as 2 separate elements on stack
     Så     # check each digit in 2nd number for membership in first
       1å   # check if any 1 exists in the resulting list
         P  # product of stack

€Sü.å- Eu gostaria que isso funcionasse como eu pensava.
Urna Mágica do Polvo

@carusocomputing: Sim, isso teria sido ótimo. Ou apenas ü.åou €Süå.
Emigna

Por que o pareamento não funciona novamente com comandos de ponto?
Urna de polvo mágico

1
@carusocomputing: É implementado apenas para receber o próximo byte como comando. Não leva em consideração o ponto.
Emigna

6

CJam , 18 15 14 bytes

Economizou 4 bytes graças a Martin Ender

l~Afb_1>.&:,:*

Experimente online!

Explicação

l~              e# Read and eval the input
  Afb           e# Convert each number to a list of digits
     _          e# Duplicate the array
      1>        e# Slice it after the first element
        .&      e# Vectorized set intersection; take the set intersection of corresponding 
                e#  elements of the two arrays
          :,    e# Get the length of each intersection
            :*  e# Take the product of the whole array. 
                e#  Will be 0 if any intersection was empty.

6

Haskell, 51 48 35 Bytes

-3 bytes graças a @NickHansen! Eu realmente preciso melhorar com esses operadores de mônada

-4 e -9 bytes graças a @Laikoni e @nimi, respectivamente!

and.(zipWith(any.flip elem)=<<tail)

Esta versão aceita a entrada como uma matriz de seqüências de caracteres, eliminando a necessidade show, mas, tanto quanto posso ver, funciona da mesma maneira que a versão anterior:

all(\(x,y)->any(`elem`x)y).(zip=<<tail).map show

(Tenho certeza de que tenho permissão para enviar uma função anônima como esta, mas vou corrigi-la se necessário)

Primeiro, os números são convertidos em strings. Então a mônada mágica zip=<<tailcria uma função que fecha a lista consigo mesma, que emparelha cada entrada com seus vizinhos. Em seguida, allmapeia um lambda para cada par que verifica se uma sequência contém caracteres da outra e, finalmente, verifica se todas elas saem True.

Versão antiga que funciona basicamente da mesma maneira:

f a=and$zipWith(\b->any(`elem`show b).show)a$tail a

Eu consegui raspar um byte usando zip e alguns truques de mônada (->): f (x, y) = any ('elem'x) y; g = all f. (Zip = << tail) .map show . edit: elem [espero que obviamente] esteja em backticks, mas isso não é possível com o formatador de comentários.
Nick Hansen

44 bytes:and.(zipWith(any.flip elem)=<<tail).map show
Laikoni 15/17

É permitido levar a entrada como uma lista de strings, por exemplo ["1234567890", "19", "95", "5012", "23"], para que você possa largar o .map show.
N

5

Mathematica 62 47 35 bytes

Com 12 bytes salvos, graças ao MartinE.

FreeQ[#⋂#2&@@@Partition[#,2,1],{}]&

FreeQ[#⋂#2&@@@Partition[#,2,1],{}]&[{{1},{1,2},{2,0,3},{0},{3,1}}]

Falso

FreeQ[#⋂#2&@@@Partition[#,2,1],{}]&[{{1},{1,2},{2,0,3},{0},{3,0}}]

Verdade


4

Ruby, 49 48 bytes

->x{x.each_cons(2){|z|x&&=z*' '=~/(.).* .*\1/};x}

A saída é nilpara false e um número inteiro "aleatório" para true.


4

Java 8, 94 90 87 bytes

Entrada é uma matriz de cadeias que representam os números. Começando com a segunda corda, ele executa uma comparação expressão regular contra cada corda anterior para ver se ele contém qualquer uma de suas personagens: .*[previous string].*.

Golfe:

a->{int r=1,i=0;while(++i<a.length)r*=a[i].matches(".*["+a[i-1]+"].*")?1:0;return r>0;}

Ungolfed:

public class NumberChainingPredicate {

  public static void main(String[] args) {
    System.out.println("Expect true:");
    for (String[] input : new String[][] { { "1", "1", "1", "11", "111", "11", "1" }, { "12", "23", "34", "45", "56" },
        { "65", "54", "43", "32", "21" }, { "123", "29", "9", "59", "55", "52", "2017", "2" },
        { "1234567890", "19", "95", "5012", "23" } }) {
      System.out.println(java.util.Arrays.toString(input) + " = " + exec(f(), input));
    }

    System.out.println();
    System.out.println("Expect false:");
    for (String[] input : new String[][] { { "1", "2", "3", "4", "5", "1", "11" }, { "12", "23", "33", "45" },
        { "98", "87", "76", "11", "12", "23" } }) {
      System.out.println(java.util.Arrays.toString(input) + " = " + exec(f(), input));
    }
  }

  private static java.util.function.Function<String[], Boolean> f() {
    return a -> {
      int r = 1, i = 0;
      while (++i < a.length) {
        r *= a[i].matches(".*[" + a[i - 1] + "].*") ? 1 : 0;
      }
      return r > 0;
    };
  }

  private static boolean exec(java.util.function.Function<String[], Boolean> function, String[] input) {
    return function.apply(input);
  }

}

Agradável! Muito mais curto do que eu estava prestes a postar. De qualquer forma, você pode jogar golfe um pouco mais: a->{for(int i=1;i<a.length;)if(!a[i].matches(".*["+a[i++-1]+"].*"))return 0>1;return 1>0;}( 90 bytes )
Kevin Cruijssen 15/17

Eu também jogava golfe até 90, mas de uma maneira diferente: #a->{int r=1;for(int i=0;++i<a.length;)r*=a[i].matches(".*["+a[i-1]+"].*")?1:0;return r>0;}
Business Cat

1
Não importa, chegou a 87: #a->{int r=1,i=0;for(;++i<a.length;)r*=a[i].matches(".*["+a[i-1]+"].*")?1:0;return r>0;}
Business Cat

Graças a vocês dois. Penso que a única maneira de melhorar isso agora de maneira significativa é olhar para o regex.

4

Gelatina , 6 bytes

Dµf"ḊẠ

Experimente online!

Explicação

Dµf"ḊẠ
Dµ        Treat the first (i.e. only) input as a list of decimal digits
   "      For each pair of corresponding elements in {the input digits} and
    Ḋ     {the input digits} with the first element removed
  f       take all elements common to both sides
     Ạ    then return true if the result has no empty lists, false otherwise

É mais óbvio tentar usar 2/aqui, mas isso executa uma função unária em todas as fatias de tamanho 2. "Ḋefetivamente executa uma função binária em todos os pares de elementos adjacentes, o que significa que podemos usar fdiretamente (em vez de precisar convertê-la em unária) funcionar como f/). Isso acaba deixando o último elemento da entrada no lugar, mas felizmente nem mesmo uma entrada de 0 se torna uma lista vazia quando convertida em decimal, portanto, não tem efeito na .



3

Geléia , 8 bytes

Dœ&L¥2\Ạ

Experimente online!

Quão?

Dœ&L¥2\Ạ - Main link: the list of integers            e.g. [3, 13, 351, 73, 82]
D        - convert all the integers to decimal lists       [[3],[1,3],[3,5,1],[7,3],[8,2]]
     2\  - 2-slice cumulative reduce with:
    ¥    -     last two links as a dyad:
 œ&      -         multiset intersection                   [[3],[1,3],[3],[]]
         -         length                                  [1,2,1,0]
       Ạ - all truthy?                                     0

3

05AB1E , 5 bytes

Código:

üÃõå_

Usa a codificação CP-1252 . Experimente online! ou Verifique todos os casos de teste!.

Explicação:

üà         # Intersection on each pair
  õå       # Check if the empty string exists
    _      # Boolean negate

Oh cara, isso funciona! RüÃõå_foi o que eu criei por conta própria. Sinto-me honrado por ter estado tão perto da sua melhor resposta, excluindo a minha. Por que você não precisa do Rpensamento?
Urna de polvo mágico

1
@carusocomputing Hmmm, para que serve Rentão? : p
Adnan

2

PowerShell , 87 bytes

param($n)(1..($a=$n.length-1)|?{[char[]]$n[($i=$_)-1]|?{$n[$i]-like"*$_*"}}).count-eq$a

Experimente online!

Não é o mais curto em nenhuma medida, mas uma abordagem um pouco diferente do que os outros estão usando e mostra a |?{}funcionalidade bacana .

Isso leva a entrada como uma matriz de strings para $n, em seguida, faz um loop de 1até o length-1. Usamos Where-Object(the |?{...}) para obter os índices verdadeiros para uma condição específica. Você pode pensar nisso como um forloop de combinação com umif cláusula.

A cláusula aqui é [char[]]$n[($i=$_)-1]|?{$n[$i]-like"*$_*"}. Ou seja, estamos pegando o índice atual $_, configurando-o $ie subtraindo-o 1e usando-o para indexar $n(ou seja, para obter o elemento anterior em nossa matriz de entrada). Que é então lançado como um chararray e enviado através de outroWhere-Object procedimento.

A cláusula interna $n[$i]-like"*$_*"especifica que a sequência no índice atual $ié -likeo caractere atual$_ do índice anterior. Portanto, será gerado qualquer caractere comum entre os dois elementos da matriz. Portanto, a cláusula externa somente será verdadeira se houver um caractere em comum (já que uma matriz vazia é falsey no PowerShell) e, portanto, o índice será selecionado apenas se houver caracteres em comum.

Em seguida, reunimos todos os índices que correspondiam aos critérios e verificamos se o .countmesmo corresponde -eqao comprimento da matriz de entrada. Esse resultado booleano é deixado no pipeline e a saída é implícita.




2

PHP, 65 68

for(;null!==$a=$argv[++$i+1];)$r+=$a==strtr($a,$argv[$i],_);echo!$r;

itere sobre todos os números e remova todos os dígitos que apareceram no anterior. Conte quantas vezes ele é igual ao número em si (nenhum dígito removido). Se pelo menos um igualasse, não tínhamos correspondência em nenhum dos pares.


Corrigido um erro usando triminsted destrtr . Obrigado a @ JörgHülsermann


Um grande desculpa. para os casos de teste fornecidos, sua solução funciona. ["filename",1,11,414]funciona não.
Jörg Hülsermann 16/03/19

O @ JörgHülsermann certamente trimsó funciona para os caracteres à esquerda e à direita. Corrigido.
Christoph

Para PHP <7.1, você pode usar em a&vez de null!==(-5 bytes).
Titus

... mas isso só funcionará para o primeiro dígito $argv[$i], porque "Se de e para ter comprimentos diferentes, os caracteres extras no mais longo dos dois serão ignorados". (do manual)
Tito

2

PHP, 75 bytes

for($b=3**39;--$argc;)preg_replace("#[$b]#","",$b=$argv[$argc])<$b?:die(1);

recebe números dos argumentos da linha de comando; sai com 1para falsidade, com 0para verdade.
Execute -rou teste on-line .

  • comece com $b= um número que contém todos os dígitos
  • percorrer os argumentos
    • remova todos os dígitos do $bargumento
    • copiar argumento para $b
    • se nenhum dígito foi removido, saia com 1
  • implícito: exit com 0

1

PHP, 77 bytes

for($i=$t=1;++$i<$argc;)$t*=preg_match("#[{$argv[$i-1]}]#",$argv[$i]);echo$t;

1
Alternativa: foreach($argv as$k=>$v)$t=$k--?$t*preg_match("#[{$argv[$k]}]#",$v)):1;echo$t;77 bytes (não testado).
Ismael Miguel

1
@IsmaelMiguel pesada alternativa Primeiro você deve mudar $k--para --$ke soltar um) depois que a sua abordagem deve funcionar e você deve adicionar um @ para o aviso
Jörg Hülsermann

Ah, sim, não percebeu os parênteses inúteis que causam erros de sintaxe. E eu discordo sobre o $k--. Eu o usei especificamente para que $ k ainda seja 0 na primeira execução. E os avisos são ignoráveis. Isso significa que o código agora é de 76 bytes, mas ainda não foi testado.
Ismael Miguel

Após a edição, posso confirmar que foreach($argv as$k=>$v)$t=$k--?$t*preg_match("#[{$argv[$k]}]#",$v):1;echo$t;está funcionando como deveria. Teste com $argv = array(1, 12, 123, 3, 34, 45, 5, 5);telas 1e testes com $argv = array(1, 12, 123, 3, 34, 45, 5, 6);telas 0, conforme o esperado.
Ismael Miguel

@IsmaelMiguel Você esquece que o primeiro parâmetro no é o nome do arquivo.
Jörg Hülsermann 16/03/19

1

MATL , 14 bytes

1&)"V@VX&nv@]x

Experimente online!

Obrigado @LuisMendo por salvar um byte. Explicação:

1&)            % 'Pop' the first item from the input and push it on the stack.
   "       ]   % Main 'for' loop, to loop over the rest of the input.
    V            % Stringify previous (or first) iten from the input.
     @V          % Push current number, convert to string
       X&        % Intersect with stringified number already on the stack.
         nv      % Count the size of the intersection, and add it to the existing list of sizes.
           @     % Push the current number again for the intersection in the next loop. 
             x % Remove the number pushed by the last loop.
               % Else the program would end with the result on the second instead of the first position in the stack

Você pode salvar um byte substituindo 1)VGpor 1&)(e isso evita repetir o primeiro número)
Luis Mendo

@LuisMendo Claro! Lembrei-me vagamente de que o MATL tinha essa funcionalidade, mas pesquisar por "pop" (como em uma fila ou pilha) na especificação não produziu nenhum resultado, então pensei que estava enganado.
Sanchises 15/03

Sim, na verdade, é um caso particular de indexação de referência. Com duas saídas, uma operação de indexação de referência )fornece os valores selecionados como primeira saída e, em seguida, os valores restantes como segunda saída.
Luis Mendo

@LuisMendo Clever. Eles devem contratar você MATL caras para melhorar MATLAB ...
Sanchises

Haha Eu sinto falta algumas destas características em MATLAB, por vezes
Luis Mendo

1

Clojure, 71 bytes

(fn[n](every?(fn[[q w]](some q w))(partition 2 1(map #(set(str %))n))))

Uma função anônima que aceita uma sequência de números. Devoluções true/false .

Eu gosto de como se lê. Definitivamente, existem algumas áreas que podem ser aprimoradas aqui. Minha função transmitida mapnão pode ser alterada facilmente, de modo que não exija a macro de função, o que significa que toda a função não pode usar a macro, o que provavelmente adicionou alguns bytes. Também seria bom se eu pudesse descobrir uma maneira melhor de descompactar os valores no every?predicado.

(defn number-chain? [nums]
  (let [; Turn each number into a set of characters
        set-nums (map #(set (str %)) nums)

        ; Partition the sets into lists of neighbors
        ; [1 2 3 4] -> [[1 2] [2 3] [3 4]]
        partitioned (partition 2 1 set-nums)]

    ; Does every second neighbor contain some element of the first?
    (every?
      (fn [[l1 l2]]
        (some l1 l2))
      partitioned)))

1

SimpleTemplate, 124 bytes

Uau, isso foi um treino!

{@eachargv asA keyK}{@ifK}{@setR"/[",O,"]/"}{@calljoin intoR"",R}{@ifA is notmatchesR}{@return}{@/}{@/}{@setO A}{@/}{@echo1}

Isso "simplesmente" cria uma regex usando o elemento antigo, mostrando 1como um valor verdadeiro ou nada mais.


Ungolfed:

{@each argv as number key K}
    {@if K}
        {@set regex "/[", old, "]/"}
        {@call join into regex "", regex}
        {@if number is not matches regex}
            {@return false}
        {@/}
    {@/}
    {@set old number}
{@/}
{@echo 1}

1

JavaScript (ES6), 37 bytes

s=>/^(.*(.).*\n(?=.*\2))+.+$/.test(s)

Aceita entrada como uma sequência de números separados por nova linha. Com base na excelente resposta Retina de @ MartinEnder ♦, mas fazendo o teste inteiro em uma única regexp, porque dessa forma é mais curto em JavaScript.


1

Pip , 12 10 bytes

$&B@X^_MPg

Recebe entrada como uma série de argumentos da linha de comando. Saída é uma lista não vazia para a verdade e uma lista vazia para falsey. Experimente online ou verifique todos os casos de teste .

Explicação

         g  List of all cmdline args
       MP   Map this function to consecutive pairs of items from that list:
     ^_      Split 1st item of pair into list of characters
    X        Convert to regex that matches any of those characters
  B@         Find all matches in 2nd item of pair
$&          Fold on logical AND--truthy if all items are truthy, falsey if one is falsey
            Print (implicit)

1

Röda , 45 35 bytes

{[_=~`(\S*(\S)\S* (?=\S*\2))+\S+`]}

Experimente online!

Isso é semelhante à solução Perl 5, que é uma porta da solução Retina de Martin Ender. -10 bytes graças a @Neil.

Aqui está uma solução diferente ( 73 72 bytes):

{[_/""]|{|x|{x|[0]()unless[not(_ in y)]else[1]}if tryPeek y}_|sum|[_=0]}

É uma função anônima que extrai cadeias de caracteres do fluxo e verifica se as cadeias consecutivas contêm os mesmos caracteres. Explicação:

{
    [_/""]|    /* split strings -> creates arrays of characters */
    {|x|       /* begin for loop over character arrays */
        {      /* begin if tryPeek(y) -> peeks the second item from the stream */
               /* x and y are now two consecutive character arrays */
            x| /* push characters in x to the stream */
            [0]()unless[not(_ in y)]else[1] /* pushes 0 to the stream */
                                            /* if y contains the character */
                                            /* in the stream, otherwise 1 */
        }if tryPeek y
    }_|        /* end for loop */
    sum|       /* sum all numbers in the stream */
    [_=0]      /* return true if the sum is zero */
}

Possivelmente poderia ser jogado mais ...


Seria bom ter uma única regexp que faça todo o teste de uma só vez? Algo como ^(\S*(\S)\S* (?=\S*\2))+\S+$.
Neil

@ Neil Isso parece funcionar. Obrigado!
Fergusq

1

Utilitários Bash + Unix, 71 69 bytes

sed "s/\(.*\)/<<<\1 \&\&grepx[\1]/;1s/.*g/g/;\$s/ .*//"|tr 'x
' \ |sh

Experimente online!

A entrada está em stdin, um número por linha.

A saída está no código de saída: 0 para truthy, 1 para falsey.

Provavelmente isso pode ser jogado mais.

Para que o código acima funcione, não pode haver nenhum arquivo no diretório atual cujo nome seja um único dígito. Se isso não for aceitável, substitua [\1]no programa por'[\1]' (a um custo de 2 bytes adicionais).

Execução de amostra (o último caso de teste fornecido no desafio):

$ echo '98
> 87
> 76
> 11
> 12
> 23' | ./digittest > /dev/null; echo $?
1

(1 aqui é falsey.)


Como funciona:

Vou demonstrar na amostra executada acima.

O comando sed converte a entrada em:

grepx[98]
<<<87 &&grepx[87]
<<<76 &&grepx[76]
<<<11 &&grepx[11]
<<<12 &&grepx[12]
<<<23

O comando tr converte isso para a string:

grep [98] <<<87 &&grep [87] <<<76 &&grep [76] <<<11 &&grep [11] <<<12 &&grep [12] <<<23

Essa string é um comando shell para realizar a operação desejada, então eu canalizo isso para sh e pronto.


A restrição de arquivo é boa, embora essa seja certamente uma limitação estranha.
Carcigenicate

1

Q, 57 bytes

{r::();({r,::any(last x)in y;x,enlist y}\)($)0,x;all 1_r}
  1. Inicializa r global.
  2. Converte entrada em matriz de seqüências de caracteres.
  3. Verifica a matriz, verificando se algum caractere na última sequência está na sequência atual.
  4. Anexa cada resultado a r.
  5. Retorna 1 se todas as seqüências de caracteres satisfizerem a etapa 3 e retornará 0.

Nota: 0 anexado ao início da matriz de entrada na função. Isso foi feito para que a comparação do primeiro elemento fosse realizada. Caso contrário, o último caractere do primeiro elemento é capturado para comparação. No entanto, poderia fazer uma verificação de tipo que adiciona 7 bytes à contagem atual.


Parece uma abordagem semelhante à minha resposta do Clojure. Linguagem elegante.
Carcigenicato
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.