Agrupar números inteiros por originalidade

11

Introdução:

Eu coleciono quebra-cabeças sinuosos. A maioria dos quebra-cabeças sinuosos são produzidos e vendidos por empresas chinesas. A maioria das empresas conhecidas solicita aos criadores de quebra-cabeças permissão para produzir seus desenhos e trabalhar juntos em direção a um produto no mercado. Nesse caso, é claro que os designers de quebra-cabeças estão muito felizes e orgulhosos por um de seus quebra-cabeças chegar ao mercado.

No entanto, também existem empresas chinesas que fazem quebra-cabeças. Esses imitações são designs usados ​​sem a permissão do criador original ou são cópias de qualidade inferior mais baratas de quebra-cabeças já existentes.

Desafio:

Vamos determinar a originalidade dos números que são 'liberados' em uma ordem específica (da esquerda para a direita ).
Dada uma lista de números inteiros, agrupe e produza-os por sua originalidade.

Como é determinada a originalidade dos números?

  • Um número é uma duplicata exata de um número anterior? Grupo X+1 (menos original), onde o grupo está à direita, depois de todos os outros grupos.X+1
  • Um número é uma duplicata de um número anterior, mas é negativo (por exemplo, o número original era , mas agora ; ou vice-versa)? Grupo .nnX
  • O valor absoluto do número pode ser formado concatenando um ou mais números absolutos anteriores e não faz parte dos grupos mencionados anteriormente ou ? Grupo , em que é a quantidade de números distintos usados ​​na concatenação (e ).X+1XXNNN1
  • O número não se encaixa em nenhum dos grupos acima, portanto, é completamente único até agora? Grupo 1 (mais original), que lidera antes de todos os outros grupos.

Isso pode parecer bastante vago, então aqui está um exemplo passo a passo :

Lista de entrada: [34,9,4,-34,19,-199,34,-213,94,1934499,213,3,21,-2134,44449,44]

  • 34é o primeiro número, sempre original e no grupo 1 . Saída até agora:[[34]]
  • 9 também é original: [[34,9]]
  • 4 também é original: [[34,9,4]]
  • -34é o negativo do número anterior 34, por isso está no grupo X :[[34,9,4],[-34]]
  • 19 é original: [[34,9,4,19],[-34]]
  • -199pode ser formado pelos dois números anteriores 19e 9, portanto, está no grupo X2 :[[34,9,4,19],[-199],[-34]]
  • 34é uma cópia exata de um número anterior, portanto, está no grupo X+1 :[[34,9,4,19],[-199],[-34],[34]]
  • -213 é original: [[34,9,4,19,-213],[-199],[-34],[34]]
  • 94pode ser formado pelos dois números anteriores 9e 4, portanto, está no grupo X2 :[[34,9,4,19,-213],[-199,94],[-34],[34]]
  • 1934499pode ser formado pelos quatro números anteriores 19, 34, 4, e duas vezes 9, por isso é no grupo X4 :[[34,9,4,19,-213],[19499],[-199,94],[-34],[34]]
  • 213é o negativo do número anterior -213, por isso está no grupo X :[[34,9,4,19,-213],[1934499],[-199,94],[-34,213],[34]]
  • 3 é original: [[34,9,4,19,-213,3],[1934499],[-199,94],[-34,213],[34]]
  • 21 é original: [[34,9,4,19,-213,3,21],[1934499],[-199,94],[-34,213],[34]]
  • -2134pode ser formado por dois números anteriores 213e 4(ou os três números anteriores 21, 3e 4, mas sempre usar a menor quantidade de concatenação de números para determinar a originalidade), por isso é no grupo X2 :[[34,9,4,19,-213,3,21],[1934499],[-199,94,-2134],[-34,213],[34]]
  • 44449pode ser formado pelos dois números anteriores quatro vezes 4e 9, portanto, está no grupo X2 :[[34,9,4,19,-213,3,21],[1934499],[-199,94,-2134,44449],[-34,213],[34]]
  • 44pode ser formado por um único número anterior 4, repetido duas vezes, por isso está no grupo X1 : [[34,9,4,19,-213,3,21],[1934499],[-199,94,-2134,44449],[44],[-34,213],[34]]

Então, para entrada, [34,9,4,-34,19,-199,34,-213,94,1934499,213,3,21,-2134,44449,44]a saída é [[34,9,4,19,-213,3,21],[1934499],[-199,94,-2134,44449],[44],[-34,213],[34]].

Regras do desafio:

  • A E / S é flexível. Você pode inserir como uma lista / matriz / fluxo de números inteiros ou seqüências de caracteres, inseri-los um a um por meio de STDIN, etc. A saída pode ser um mapa com os grupos como chave, uma lista aninhada como exemplo e casos de teste neste desafio, impressos nova linha separada etc.
  • Você pode receber a lista de entrada em ordem inversa (talvez útil para idiomas baseados em pilha). Nesse caso, a esquerda para a direita mencionada é obviamente da direita para a esquerda.
  • Como você pode ver no exemplo de inteiro -2134, nós sempre grupo um número que é uma concatenação de outros números, com o mínimo possível (formada por 213e 4- dois números, e não por 21, 3e 4- três números).
  • Como você pode ver no exemplo para número inteiro 1934499, você pode usar um número anterior ( 9neste caso) várias vezes (semelhante ao 44449uso de quatro se 4um 9no exemplo). Eles são contados apenas uma vez para determinar o grupo.
  • [1,58,85,-8,5,8585,5885,518][[1,58,85,8,5],[518],[5885],[8585],[],[]]XX1[[34,9,4,19,-213,3,21],[1934499],[],[-199,94,-2134,44449],[44],[-34,213],[34]]X3
  • [34,9,4,19,-213,3,21]1[21,3,-213,19,4,9,34][-213,4,34,19,9,21,3]
  • X10[1,X9,X8,...,X2,X1,X,X+1]
  • Você pode assumir que os números inteiros terão 32 bits no máximo, portanto, dentro do intervalo [−2147483648,2147483647].

Regras gerais:

  • Isso é , então a resposta mais curta em bytes vence.
    Não permita que idiomas com código de golfe o desencorajem a postar respostas com idiomas que não sejam codegolf. Tente encontrar uma resposta o mais curta possível para 'qualquer' linguagem de programação.
  • As regras padrão se aplicam à sua resposta com as regras de E / S padrão , para que você possa usar STDIN / STDOUT, funções / método com os parâmetros adequados e programas completos do tipo retorno. Sua chamada.
  • As brechas padrão são proibidas.
  • Se possível, adicione um link com um teste para o seu código (ou seja, TIO ).
  • Além disso, é altamente recomendável adicionar uma explicação para sua resposta.

Casos de teste:

Input:  [34,9,4,-34,19,-199,34,-213,94,1934499,213,3,21,-2134,44449,44]
Output: [[34,9,4,19,-213,3,21],[1934499],[-199,94,-2134,44449],[44],[-34,213],[34]]

Input:  [17,21,3,-317,317,2,3,117,14,-4,-232,-43,317]
Output: [[17,21,3,2,117,14,-4],[-317,-232,-43],[317],[3,317]]

Input:  [2,4,8,10,12,-12,-102,488,10824]
Output: [[2,4,8,10,12],[10824],[-102,488],[-12]]

Input:  [0,100,-100,10000,-100,1001000]
Output: [[0,100],[10000,1001000],[-100],[-100]]

Input:  [1,58,85,-8,5,8585,5885,518]
Output: [[1,58,85,-8,5],[518],[5885],[8585]]

Input:  [4,-4,44,5,54]
Output: [[4,5],[54],[44],[-4]]
Kevin Cruijssen
fonte
Então, X + 1existe um grupo especial para cópias exatas e Xum grupo para outros números que podem ser formados a partir de cópias de um único número, como sua negação?
Neil
1
[2147483648,2147483647][1, 1111111111]
1
Ser eu mesmo um colecionador: é uma coleção muito boa, Kevin. Muito bom mesmo.
J. Sallé
1
Coleciono cards e conjuntos de Magic: The Gathering, que ainda ocupam uma quantidade surpreendentemente grande de espaço, apesar de serem relativamente pequenos.
J. Sallé
1
@ J.Sallé Oh, eu conheço o sentimento. Eu também coleciono cards de Pokémon TCG (e, na verdade, tenho a segunda maior coleção de Pikachu TCG do mundo, com mais de 1200 cartões únicos de Pikachu). Quando você tem mais de 9.000 cartões, ocupa bastante espaço. Não tanto quanto os quebra-cabeças, no entanto. Apenas 1,5 prateleiras em vez de 10.; p
Kevin Cruijssen 07/07/19

Respostas:

9

Python 3 , 565 564 524 523 500 437 399 394 393 389 385 372 bytes

Implementação de força bruta usando itertools; nem todos os casos de teste são executados dentro do limite de 60 segundos no TIO.

Experimente online!

Graças ao ArBo por jogar 101 bytes, a Galen Ivanov por 19 bytes, a ElPedro por 5 bytes, a movatica por 17 bytes, a Black Owl Kai por 2 bytes, a lula por 2 bytes e a Kevin Cruijssen por 1 byte de golfe.

from itertools import*
w=permutations
def c(l,x):
 for i in range(9):
  for q in w(map(abs,sum(l,[]))):
   for s in w(q[:i+1]*len(x)):
    z='';s=[*s]
    while x[len(z):]:
     z+=str(s.pop(0))
     if z==x:return 9-i
 return 0
def f(a):
 l=[[]for _ in a*6]
 for x in a:l[(x in sum(l,[]))*11or(-x in sum(l,[]))*10or any(l)and c(l,str(abs(x)))]+=x,
 return[*filter(len,l)]

Explicação:

from itertools import *
w = permutations  # We'll be using this twice

def c  # Helper function to calculate which group a number belongs in according to the concatenation rule; returns 0 (original) if none is found
(l, x):  # First parameter is the list of groups (a list of lists of numbers), second parameter is the number to investigate
 for i in range(9):  # There won't be any concatenations of more than 9 elements
  for q in w(map(abs,sum(l,[]))):  # Flatten l to get a plain list of previous numbers, then generate permutations of their absolute values as lists; for each permutation ...
   for s in w(q[:i+1]*len(x)):  # ... use only the first i + 1 elements; inflate the list with enough copies to compose the target number and permutate; then try to compose the target number from each permutation:
    z = ''  # Start with the empty string
    s = [*s]  # Convert permutation to list
    while x[len(z):]:  # Keep going until the length of the concatenated string equals the length of the target number
     z += str(s.pop(0))  # Concatenate the first element of the current permutation list and remove it
     if z == x:  # If the target number has been synthesized successfully ...
      return 9 - i  # stop searching and return the appropriate group
 return 0  # If no concatenation has been found, consider the number original

def f(a):  # Solution function, takes a list of numbers as argument
 l = [[] for _ in a * 6]  # Populate the result list with at least 12 empty groups if there is more than one number in the input (we'll be using only the first 12 and removing empty ones later); if there is just one, we'll only need one group in the output
 for x in a:  # For each number in order:
  l[(x in sum(l, [])) * 11 or (-x in sum(l, [])) * 10 or any(l) and c(l, str(abs(x)))] += x,  # If x is not the first number, attempt concatenation (if not, c(l, str(abs(x))) would crash due to l not containing any non-empty sublists; use absolute value of the number under investigation; convert to string since we'll be needing the number of digits and comparing it to a string later); if -x has already been seen, put it in Group X; if x has already been seen, put it in Group X + 1
  return [* filter(len, l)]  # Remove empty lists and return the result

Python 2 , 406 379 374 373 372 368 355 bytes

A mesma abordagem, mas mais curta devido a alguns truques de golfe, o Python 3 não suporta mais. Agradecimentos ao ArBo pelo backport e pelo golfe de 28 bytes, pelo ElPedro pelo golfe de 5 bytes, pela movatica pelo golfe de 17 bytes e pelo squid pelo golfe de mais 1 byte.

from itertools import*
w=permutations
def c(l,x):
 for i in range(9):
  for q in w(map(abs,sum(l,[]))):
	for s in map(list,w(q[:i+1]*len(x))):
	 z=''
	 while x[len(z):]:
		z+=`s.pop(0)`
		if z==x:return 9-i
 return 0
def f(a):
 l=[[]for _ in a*6]
 for x in a:l[(x in sum(l,[]))*11or(-x in sum(l,[]))*10or any(l)and c(l,`abs(x)`)]+=x,
 return filter(len,l)

Experimente online!

OOBalance
fonte
2
Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
James
Você pode salvar 5 em ambos movendo str(abs(x))(ou abs (x) com reticulares em Python 2) para a chamada da função e alterando x na definição da função para y removendo y = str (abs (x)). Desculpe, não é possível fazer com que o TIO funcione no momento.
ElPedro 6/06/19
Você pode filtrar lenpara remover outro byte, certo?
Reintegrar Monica
Você pode remover a sintaxe lista dentro de any()chamadas, tornando-se assim um gerador normal, que funciona tão bem e você economiza mais 4 bytes :)
movatica
... e ainda mais curto: em (x in sum(l,[]))vez de any(x in s for s in l)para ambos xe -xeconomiza mais 13 bytes!
movatica 11/06/19
7

Python 2 , 235 234 232 246 245 244 241 240 238 237 236 bytes

from itertools import*
s=[];r=map(list,[s]*12)
for e in input():r[-(e in s)or max([10*(-e in s)]+[10-len(set(p[:i]))for p in permutations(`abs(x)`for x in s*11)for i in range(len(p))if''.join(p[:i])==`e`])]+=e,;s+=e,
print filter(len,r)

Experimente online!

-1 byte, graças ao comentário do Squid sobre a outra resposta Python

Esta resposta não tem esperanças de solucionar nenhum dos casos de teste mais triviais. No link TIO, s*11foi substituído por s*2, sacrificando correção em alguns casos, para rápido er tempo de execução, mas tanto quanto eu posso ver, a versão neste post sempre produz a resposta correta, em teoria.

Explicação

from itertools import*          # So that we can abuse permutations
s=[];                           # s will hold the already classified numbers
r=map(list,[s]*12)              # r will hold these too, but in the form of
                                #  a nested list, sorted by originality
for e in input():               # Here comes the big one; iterate over the input
 r[-(e in s)or                  # If e has already passed, it is not original
   max([10*(-e in s)]+          # Else, we count 10 - the number of seen elements
                                #  needed to make this one, or 0 if it's new,
                                #  or 10 if its inverse has already passed
   [10-len(set(p[:i]))          # The number of distinct elements in...
    for p in permutations(      #  for each permutation of the seen elements,
      `abs(x)`for x in s*11)
                                #  with values occuring up to 10 times (to
                                #  account for 1111111111, for example;
                                #  we need 11 here and not 10, because
                                #  p[:i] doesn't include i)...
    for i in range(len(p))      #  each prefix...
    if''.join(p[:i])            #  only if its concatenation is equal to
      ==`e`])]                  #  the current element
 +=e,;s+=e,                     # Append the element to the relevant lists
print filter(len,r)             # And finally, print the non-empty result lists
ArBo
fonte
2
É um prazer ver que você criou sua própria resposta em Python :-) E é mais curta também!
OOBalance
@OOBalance Agora, se só ele iria encerrar dentro de minha vida ...
Arbo
1
Ah, eu esqueci como isso é uma coisa boba com a versão do Windows (ele usa apenas 32 bits, intmesmo na versão de 64 bits).
feersum
7

05AB1E , 43 41 38 35 27 bytes

.¡IN£UÄ.œεgΘ>XÄyÙå;P*}àXyå+

Experimente online!

Explicação:

.¡                              # group by:
  IN£                           #  first N elements of the input, N being the iteration count
     U                          #  store this as X
  Ä                             #  absolute value of the current number
   .œ                           #  partitions (eg 449 => [[4, 4, 9], [44, 9], [4, 49], [449]])
     ε             }            #  map each partition to:
      gΘ>                       #   2 if length = 1, 1 otherwise
           yÙ                   #   for each unique element in the current partition:
         XÄ  å                  #    1 if it's in the absolute value of X, 0 otherwise
              ;                 #   divide all by 2
               P*               #   product of all these numbers
                  à             #  take the maximum
                   Xyå+         #  add 1 if X contains the current number

Como os números de grupo não fazem parte da saída, podemos usar os números que quisermos, desde que a ordem esteja correta. Utiliza 0 para números originais, 2 ^ -N para o grupo XN, 1 para o grupo X, 2 para o grupo X + 1.

Grimmy
fonte
3
Gostaria de ver uma explicação de como isso funciona, pois não consigo ler 05AB1E.
OOBalance
@OOBalance Adicionei uma explicação, espero que seja clara o suficiente.
Grimmy
Obrigado, isso explica muito bem. Boa abordagem, tenho o meu upvote :)
OOBalance
2

Python 2, 195 bytes

O caso de teste mais lento não pode ser concluído no TIO , mas leva apenas 10 segundos na minha máquina.

import re
a=[()];m=a*99
for n in input():
    i=0;r='-('
    while i<10>re.search(r'(\b.+\b).+'*i+r+')+$','%s-%%s'%a%n):i+=1;r+='|\\'+`i`
    m[48*(n in a)|32*(-n in a)|14-i]+=n,;a+=n,
print filter(len,m)

Ele pode ser reduzido em 2 bytes nas versões LP64 Python, substituindo '%s-%%s'%a%npor `a`+'-'+`n`.

feersum
fonte
1

JavaScript (Node.js) , 211 205 bytes

a=>a.map(s=>(c[q=(G=(n,r=[],A=Math.abs,N=""+A(s))=>N[L="length"]<n[L]?0:N!=n?Math.max(0,...c.flat().map(x=>G(n+A(x),[...r,x]))):1/r?s-r?11:12:12+~new Set(r).size)``]=c[q]||[]).push(s),c=[])&&c.filter(x=>x)

Experimente online!

Usando a suposição de que existem no máximo 12 grupos.

JavaScript (Node.js) , 267 226 221 218 211 bytes

a=>a.map(s=>(c[q=(G=(n,r=[],A=Math.abs,N=""+A(s))=>N[L]<n[L]?0:N!=n?Math.max(0,...c.flat().map(x=>G(n+A(x),[...r,x]))):1/r?l-(s!=+r):l+~new Set(r).size)``]=c[q]||[]).push(s),c=[],l=a[L="length"])&&c.filter(x=>x)

Experimente online!

a=>a.map(                       // Iterate through all items:
 s=>(c[q=(
  G=(                           //  Helper function to calculate index (=GroupNo-1):
   n,                           //   Stores different (repeatable) permutations
   r=[],                        //   Stores the elements used
   A=Math.abs,
   N=""+A(s))                   //   Stores the string version of the absolute value
  =>
  N[L="length"]<n[L]?           //   If n is longer then N:
   0                            //    0 (Group 1) - no permutation found to equal the string
  :N!=n?                        //   Else if N!=n:
   Math.max(0,...c.flat().map(  //    Return max of the results of the next recursion
    x=>G(n+A(x),[...r,x])       //    for each of the elements in c
   ))
  :1/r?                         //   Else if r has only 1 item: (=+s/-s)
   s-r?11:12                    //    Return l-1 (Group X) if r=-s, and l (Group X+1) if r=s
  :12+~new Set(r).size          //   Else: return l-r.size-1 (Group X-r.size)
 )``]=c[q]||[]).push(s),        //  Push the element into the corresponding array
 c=[]                           //  Initialize an empty array
)&&c.filter(x=>x)               // Filter out all empty groups

... ou 193 bytes, se o retorno de um dicionário estiver correto:

a=>a.map(c=s=>(c[q=(G=(n,r=[],A=Math.abs,N=""+A(s))=>N[L="length"]<n[L]?-1/0:N!=n?Math.max(...d.map(x=>G(n+A(x),[...r,x]))):1/r?+!(s-r):-new Set(r).size)``]=c[q]||[]).push(s)&d.push(s),d=[])&&c

Experimente online!

Nesse caso, chave -Infinitysignifica Grupo 1 e outras chaves significa Grupo X+key.

Shieru Asakoto
fonte