Golfe minhas matrizes Ada

10

fundo

Ada é uma linguagem de programação que não é exatamente conhecida por sua concisão.

No entanto, sua sintaxe literal de matriz pode, em teoria, permitir especificações de matriz bastante concisas. Aqui está uma descrição EBNF simples da sintaxe literal da matriz (passável a bottlecaps.de :

array ::= positional_array | named_array
positional_array ::= expression ',' expression (',' expression)*
                   | expression (',' expression)* ',' 'others' '=>' expression
named_array ::= component_association (',' component_association)*
component_association ::= discrete_choice_list '=>' expression
discrete_choice_list ::= discrete_choice ('|' discrete_choice)*
discrete_choice ::= expression ('..' expression)? | 'others'

Vamos nos limitar a matrizes unidimensionais de números inteiros para simplificar. Isso significa que usaremos apenas números inteiros para os valores da expressão. Talvez em um desafio futuro possamos tentar algo mais avançado (como declarar variáveis ​​e matrizes multidimensionais). Você não precisa jogar golfe com literais inteiros .

Aqui estão alguns exemplos de literais de matriz Ada e uma representação equivalente em estilo python para maior clareza:

(1, 2, 3) = [1, 2, 3]
(1, others => 2) = [1, 2, 2, ..., 2]
(others => 1) = [1, 1, ..., 1]
(1 => 1, 2 => 3) = [1, 3]
(1|2 => 1, 3 => 2) = [1, 1, 2]
(1 => 1, 3 => 2, others => 3) = [1, 3, 2, 3, 3, ..., 3]

Desafio

O objetivo desse desafio é gerar o literal da matriz Ada com menor número de bytes para uma determinada matriz de entrada. Observe que as matrizes Ada podem iniciar a partir de qualquer índice desejado, para que você possa escolher o que deseja que o índice inicial contenha, desde que cada valor seja seqüencial. Neste exemplo, escolho iniciar em 1, o que é idiomático para Ada, no entanto, você pode optar por iniciar em qualquer outro número inteiro.

Entrada

Sua entrada consistirá em uma lista de números inteiros, em qualquer forma que seja conveniente.

Resultado

Sua saída será uma sequência de texto que representa o literal da matriz Ada válido mais curto que representa a lista de números inteiros de entrada. Você pode usar qualquer índice inicial que desejar nesta matriz, mas sua escolha (seja ela qual for) deve ser especificada em sua resposta (o índice inicial também pode ser dinâmico).

Os números inteiros devem ser representados como números decimais assinados, como nos exemplos. Esse desafio não cobre o golfe de valores inteiros.

Exemplos

aqui estão alguns exemplos:

Simple: [1, 2, 3] -> (1,2,3)
Range: [1, 1, 1, 1, 1, 1, 1,] -> (1..7=>1)
Others: [1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1] -> (6=>2,others=>1)
Multiple Ranges: [1,1,1,1,1,2,2,2,2,2,1,1,1,1,1,2,2,2,2,2,1,1,1,1,1] -> (6..10|16..20=>2,others=>1)
Tiny Ranges: [1,1,2,2,1,1,1,1,1] -> (3|4=>2,others=>1)
Far Range: [[1]*5, [2]*100, [3]*5] -> (1..5=>1,6..105=>2,others=>3)
Alternation: [1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2] -> (1|3|5|7|9|11|13|15|17=>1,others=>2)
Big Number: [1234567890,1,1234567890] -> (2=>1,1|3=>1234567890)
Big-ish Number: [1234567,1,1234567] -> (1234567,1,1234567)
Solo: [-1] -> (1=>-1)
Huge Input: [[0],[1]*1000000000] -> (0,others=>1)
Positional Others: [1, 2, 3, 3, 3, 3, 3, 3] -> (1,2,others=>3)
Range and Choice, no Others: [1,1,1,12,12,3,3,3,3,3,3,3,3,3,3,4] -> (1..3=>1,4|5=>12,6..15=>3,16=>4)

Requerimentos mínimos

  • Ofereça suporte a pelo menos 100 números e entradas de pelo menos 256 números.

  • Produza o resultado correto para todas essas entradas

    • Inclui colocar 'outros' no final
    • Inclui a colocação de um índice para matrizes de item único
  • Termine (de preferência no TIO) para cada uma das entradas acima em menos de um minuto.

Menor solução em bytes ganha!

Implementação de referência

Experimente online!

Essa implementação usa a entrada como sua matriz, com cada caractere sendo um número. Letras maiúsculas são constantes especiais para valores grandes. O argumento do programa é o 'índice inicial' a ser usado.

A seção "código" no link TIO é uma solução correta para o problema, enquanto o "cabeçalho" e o "rodapé" implementam a estrutura de teste.

LambdaBeta
fonte
3
O caso "Far Range" existe simplesmente para indicar que podemos receber dados nesse formato se escolhermos ou destacar que precisamos ser capazes de lidar com esse formato de entrada e com matrizes normais? Além disso, o último caso de teste não deveria ser apenas produzido (-1)?
Salsicha
3
O caso "Far Range" é meramente escrito para economizar espaço; a entrada real seria uma matriz plana composta por 110 números inteiros, mas a saída está correta. Seu objetivo é demonstrar casos em que a palavra-chave 'others' deve ir em um intervalo menor que tenha uma representação mais longa. ( 106..110=>3,others=>2seria mais longo) O último caso precisa ter um índice, pois a gramática não permite matrizes posicionais de elemento único ( positional_array ::= expression ',' expression (',' expression)*)
LambdaBeta 13/05/19
11
1(1=>1,others=>1)(1..100000000=>1)
2
Você poderia confirmar que (1|3=>1234567,2=>1)há outra saída válida para [1234567,1,1234567]?
Arnauld
11
Temos permissão para usar Ada como nosso idioma preferido?
Benjamin Urquhart

Respostas:

5

JavaScript (ES6),  307  304 bytes

Guardado 2 bytes graças a @KevinCruijssen

Isso é embaraçosamente longo ...

a=>[b=([...a,m=''].map(o=(v,i)=>(i?p==v?!++n:m=o[(o[p]=[o[p]&&o[p]+'|']+(n?i-n+(n>1?'..':'|')+i:i))[m.length]?(x=i-n,j=p):j]:1)&&(p=v,M=n=0)),Object.keys(o).map(k=>j-k|!m[6]?o[k]+'=>'+k:O,O='others=>'+j).sort()),1/a[1]?[...a]:b,j-a.pop()?b:a.slice(0,x-1)+[,O]].map(a=>M=M[(s=`(${a})`).length]||!M?s:M)&&M

Experimente online!

Arnauld
fonte
305 bytes (-2) criando uma variável para o duplicado 'others=>'.
Kevin Cruijssen 15/05/19
@KevinCruijssen Thanks! (NB: Na sua versão, té usado antes de ser definido; a razão pela qual ele não falha é que os 2 primeiros casos de teste não o utilizam; isso pode ser facilmente corrigido sem nenhum custo.)
Arnauld
Ah ok. Eu realmente não desafiei sua resposta para ver o que era usado onde. Eu simplesmente notei que você tinha 'others'duas vezes e tentou criar uma variável para ela sem alterar a saída. ;) Obrigado por explicá-lo, e bom golfe da vírgula usando [,O]. :)
Kevin Cruijssen 15/05/19
2

05AB1E , 136 134 132 bytes

"',ý'(ì')«ˆ"©.V"θ…ˆ†=>쪮.V"Uγ¨D€gPi˜IX.V}\ÙεQƶ0KDāαγ€g£}D2Fε¾iεнyg≠iyθyg<i'|ë„..}ý}}ë˜}'|ý„=>«Iyнн<è«}Ю.VgFDN._ć'>¡X.V}\¼}¯éIgi¦}н

EDIT: Corrigido para todos os casos de teste agora.

Faça o teste on-line ou verifique todos os casos de teste (exceto o de "Entrada enorme", pois é muito grande).

Explicação:

"',ý'(ì')«ˆ"       # Push this string (function 1), which does:
 ',ý              '#  Join a list by ","
    '(ì           '#  Prepend a "("
       ')«        '#  Append a ")"
          ˆ        #  Pop and add it to the global array
            ©      # Store this string in the register (without popping)
             .V    # And execute it as 05AB1E code on the (implicit) input-list
"θ…ˆ†=>쪮.V"      # Push this string (function 2), which does:
 θ                 #  Pop and push the last element of the list
  …ˆ†=>ì           #  Prepend dictionary string "others=>"
        ª          #  Append that to the list which is at the top of the stack
         ®.V       #  And execute function 1 from the register     
             U     # Pop and store this string in variable `X`
γ                  # Get the chunks of equal elements in the (implicit) input-list
 ¨                 # Remove the last chunk
  D                # Duplicate the list of remaining chunks
   g              # Get the length of each
     Pi     }      # If all chunk-lengths are 1:
       ˜           #  Flatten the list of remaining chunks
        I          #  Push the input-list
         X.V       #  Execute function 2 from variable `X`
             \     # Discard the top of the stack (in case we didn't enter the if-statement)
Ù                  # Uniquify the (implicit) input-list
 ε                 # Map each unique value `y` to:
  Q                #  Check for each value in the (implicit) input-list if it's equal to `y`
                   #  (1 if truthy; 0 if falsey)
   ƶ               #  Multiply each by its 1-based index
    0K             #  Remove all 0s
      D            #  Duplicate it
       ā           #  Push a list [1, length] without popping the list itself
        α          #  Get the absolute difference at the same indices
         γ         #  Split it into chunks of the same values
          g       #  Get the length of each
            £      #  And split the duplicated indices-list into those parts
                   # (this map basically groups 1-based indices per value.
                   #  i.e. input [1,1,2,1,1,2,2,1,1] becomes [[[1,2],[4,5],[8,9]],[[3],[6,7]]])
 }D                # After the map: duplicate the mapped 3D list
   2F              # Loop 2 times:
     ε             #  Map the 3D list of indices to:
      ¾i           #   If the counter_variable is 1:
        ε          #    Map each list `y` in the 2D inner list to:
         н         #     Leave the first value
         ygi      #     And if there is more than one index:
             yθ    #      Push the last value as well
             yg<i  #      If there are exactly two indices:
              '|  '#       Push string "|"
             ë     #      Else (there are more than two indices)
              „..  #       Push string ".."
                 #      And join the first and last value by this string
        }}         #    Close the if-statement and map
      ë            #   Else:
       ˜           #    Flatten the 2D list
      }'|ý        '#   After the if-else: join by "|"
          „=>«     #   Append "=>"
       yнн         #   Get the very first index of this 2D list
          <        #   Decrease it by 1 to make it 0-based
      I    è       #   And index it into the input-list to get its value again
            «      #   Which is also appended after the "=>"
                 #  After the map: triplicate the result
       ®.V         #  Execute function 1 from the register
       g           #  Get the amount of items in the triplicated list
        F          #  Loop that many times:
         D         #   Duplicate the list
          N._      #   Rotate it the index amount of times
          ć        #   Extract the head; pop and push remainder and head
           '>¡    '#   Split this head by ">"
              X.V  #   And then function 2 is executed again from variable `X`
        }\         #  After the loop: discard the list that is still on the stack
          ¼        #  And increase the counter_variable by 1
                 # After looping twice: push the global array
     é             # Sort it by length
      Igi }        # If the input only contained a single item:
         ¦         #  Remove the very first item
           н       # And then only leave the first item
                   # (which is output implicitly as result)

Veja este 05AB1E ponta do meu (seção Como cordas compressa não fazem parte do dicionário? ) Para entender por que …ˆ†=>é "others=>".

Kevin Cruijssen
fonte