Raggruppa numeri interi per originalità


12

Introduzione:

Colleziono puzzle intricati. La maggior parte dei puzzle intricati sono prodotti e venduti da aziende cinesi. Le aziende più famose chiedono il permesso ai progettisti di puzzle di produrre i loro progetti e lavorare insieme per un prodotto sul mercato. In questo caso, i progettisti di puzzle sono ovviamente molto felici e orgogliosi che uno dei loro puzzle abbia colpito il mercato.

Esistono tuttavia anche società cinesi che realizzano puzzle a eliminazione diretta. Questi knock-off sono o disegni utilizzati senza il permesso del creatore originale, oppure sono copie decisamente più economiche di puzzle già esistenti.

Sfida:

Determineremo l'originalità dei numeri che vengono "rilasciati" in un ordine specifico (da sinistra a destra ).
Dato un elenco di numeri interi, raggruppali e generali in base alla loro originalità.

Come viene determinata l'originalità dei numeri?

  • Un numero è un duplicato esatto di un numero precedente? Gruppo (meno originale), in cui il gruppo è in coda, dopo tutti gli altri gruppi.X+1X+1
  • Un numero è un duplicato di un numero precedente, ma è invece negativo (ovvero il numero originale era , ma ora ; o viceversa)? Gruppo .nnX
  • Il valore assoluto del numero può essere formato concatenando uno o più numeri assoluti precedenti e non fa parte dei precedenti gruppi o ? Gruppo , dove è la quantità di numeri distinti utilizzati nella concatenazione (e ).X+1XXNNN1
  • Il numero non rientra in nessuno dei gruppi sopra indicati, quindi è completamente unico finora? Gruppo (il più originale), che precede tutti gli altri gruppi.1

Questo può sembrare piuttosto vago, quindi ecco un esempio dettagliato :

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

  • 34è il primo numero, che è sempre originale e nel gruppo . Uscita finora:1[[34]]
  • 9 è anche originale: [[34,9]]
  • 4 è anche originale: [[34,9,4]]
  • -34è il negativo del numero precedente 34, quindi è nel gruppo :X[[34,9,4],[-34]]
  • 19 è originale: [[34,9,4,19],[-34]]
  • -199può essere formato dai due numeri precedenti 19e 9, quindi, è nel gruppo :X-2[[34,9,4,19],[-199],[-34]]
  • 34è una copia esatta di un numero precedente, quindi è nel gruppo :X+1[[34,9,4,19],[-199],[-34],[34]]
  • -213 è originale: [[34,9,4,19,-213],[-199],[-34],[34]]
  • 94può essere formato dai due numeri precedenti 9e 4, quindi, è nel gruppo X-2 :[[34,9,4,19,-213],[-199,94],[-34],[34]]
  • 1934499può essere formato dai quattro numeri precedenti 19, 34, 4, e due volte 9, quindi è nel gruppo X-4 :[[34,9,4,19,-213],[19499],[-199,94],[-34],[34]]
  • 213è il negativo del numero precedente -213, quindi è nel gruppo X :[[34,9,4,19,-213],[1934499],[-199,94],[-34,213],[34]]
  • 3 è originale: [[34,9,4,19,-213,3],[1934499],[-199,94],[-34,213],[34]]
  • 21 è originale: [[34,9,4,19,-213,3,21],[1934499],[-199,94],[-34,213],[34]]
  • -2134può essere formato da due numeri precedenti 213e 4(o dei tre numeri precedenti 21, 3e 4, ma usiamo sempre la minor quantità di concatenare i numeri per determinare l'originalità), quindi è nel gruppo X-2 :[[34,9,4,19,-213,3,21],[1934499],[-199,94,-2134],[-34,213],[34]]
  • 44449può essere formato dai due numeri precedenti quattro volte 4e 9, quindi, è nel gruppo X-2 :[[34,9,4,19,-213,3,21],[1934499],[-199,94,-2134,44449],[-34,213],[34]]
  • 44può essere formato da un singolo numero precedente 4, ripetuto due volte, quindi è nel gruppo X-1 : [[34,9,4,19,-213,3,21],[1934499],[-199,94,-2134,44449],[44],[-34,213],[34]]

Quindi per l'input [34,9,4,-34,19,-199,34,-213,94,1934499,213,3,21,-2134,44449,44]l'uscita è [[34,9,4,19,-213,3,21],[1934499],[-199,94,-2134,44449],[44],[-34,213],[34]].

Regole della sfida:

  • L'I / O è flessibile. Puoi inserire un elenco / matrice / flusso di numeri interi o stringhe, inserirli uno per uno tramite STDIN, ecc. L'output può essere una mappa con i gruppi come chiave, un elenco nidificato come esempio e casi di prova in questa sfida, stampati newline separato, ecc.
  • È consentito prendere l'elenco di input in ordine inverso (forse utile per le lingue basate su stack). Nel qual caso il menzionato da sinistra a destra è ovviamente da destra a sinistra.
  • Come si può vedere l'esempio per intero -2134, abbiamo sempre gruppo un numero che è una concatenazione di altri numeri con il meno possibile (formata da 213e 4- due numeri, e non da 21, 3e 4- tre numeri).
  • Come puoi vedere nell'esempio per intero 1934499, puoi usare un numero precedente (il 9in questo caso) più volte (simile con l' 44449utilizzo di quattro se 4un 9esempio nell'esempio). Tuttavia, vengono conteggiati una sola volta per determinare il gruppo.
  • Non è consentito avere elenchi interni vuoti nell'output per gruppi vuoti. Quindi test case [1,58,85,-8,5,8585,5885,518]potrebbe non comportare [[1,58,85,8,5],[518],[5885],[8585],[],[]]invece, dove i gruppi vuoti sono X e X-1 , e l'esempio sopra potrebbe non comportare [[34,9,4,19,-213,3,21],[1934499],[],[-199,94,-2134,44449],[44],[-34,213],[34]]invece, dove il gruppo vuoto è X-3 .
  • L'ordine dei gruppi è rigoroso (a meno che non si utilizzi una mappa, poiché i gruppi possono quindi essere dedotti dalle chiavi), ma l'ordine dei numeri all'interno di un gruppo può essere in qualsiasi ordine. Quindi [34,9,4,19,-213,3,21]per il gruppo 1 nell'esempio sopra può essere anche [21,3,-213,19,4,9,34]o [-213,4,34,19,9,21,3].
  • Si garantisce che non ci saranno mai numeri che possono essere formati da più di nove numeri precedenti. In modo da non avere alcun X-10 gruppi, e la più grande quantità di gruppi possibili è 12: [1,X-9,X-8,...,X-2,X-1,X,X+1]
  • Puoi supporre che i numeri interi saranno al massimo di 32 bit, quindi all'interno dell'intervallo [−2147483648,2147483647].

Regole generali:

  • Questo è , quindi vince la risposta più breve in byte.
    Non lasciare che le lingue di code-golf ti scoraggino dal pubblicare risposte con lingue non codegolfing. Prova a trovare una risposta il più breve possibile per "qualsiasi" linguaggio di programmazione.
  • Le regole standard si applicano alla tua risposta con le regole I / O predefinite , quindi puoi utilizzare STDIN / STDOUT, funzioni / metodo con i parametri corretti e tipo di ritorno, programmi completi. La tua chiamata.
  • Le scappatoie predefinite sono vietate.
  • Se possibile, aggiungi un link con un test per il tuo codice (ad es. TIO ).
  • Inoltre, si consiglia vivamente di aggiungere una spiegazione per la risposta.

Casi test:

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]]

Quindi X + 1è un gruppo speciale per copie esatte ed Xè un gruppo per altri numeri che può essere formato da copie di un singolo numero, come la sua negazione?
Neil,

1
[-2147483648,2147483647][1, 1111111111]

1
Essendo anch'io un collezionista: è una collezione dannatamente bella che ci sei arrivato, Kevin. Davvero molto bello.
J. Sallé,

1
Colleziono carte e set di Magic: The Gathering, che occupano ancora una quantità sorprendentemente grande di spazio anche se sono abbastanza piccoli.
J. Sallé,

1
@ J.Sallé Oh, conosco la sensazione. Colleziono anche carte Pokémon TCG (e attualmente ho la seconda più grande collezione Pikachu TCG al mondo con più di 1200 carte Pikachu uniche). Quando hai più di 9000 carte, occupa davvero un po 'di spazio. Tuttavia, non tanto quanto i puzzle. Solo 1,5 ripiani anziché 10.; p
Kevin Cruijssen,

Risposte:



9

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

Implementazione della forza bruta utilizzando itertools; non tutti i casi di test vengono eseguiti entro il limite di 60 secondi su TIO.

Provalo online!

Grazie ad ArBo per giocare a golf 101 byte, a Galen Ivanov per giocare a golf 19 byte, a ElPedro per giocare a golf 5 byte, a movatica per giocare a golf 17 byte, a Black Owl Kai per giocare a golf 2 byte, a calamari per giocare a golf 2 byte e a Kevin Cruijssen per golf 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 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)]

Spiegazione:

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 byte

Lo stesso approccio, ma più breve a causa di alcuni trucchi del golf Python 3 non supporta più. Grazie ad ArBo per il backport e per giocare a golf a 28 byte, a ElPedro per giocare a golf a 5 byte, a movatica per giocare a golf a 17 byte e al calamaro per giocare a golf con 1 byte in più.

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)

Provalo online!


2
I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
James,

Puoi salvare 5 in entrambi spostando str(abs(x))(o abs (x) con i backtick in Python 2) alla chiamata della funzione e cambiando x nella definizione della funzione in y rimuovendo y = str (abs (x)). Spiacenti, al momento non riesco a far funzionare TIO.
ElPedro,

Puoi filtrare lenper radere via un altro byte, giusto?
calamari

Puoi rimuovere la sintassi dell'elenco all'interno delle any()chiamate, rendendolo così un normale generatore, che funziona altrettanto bene e ti fa risparmiare altri 4 byte :)
movatica,

... e ancora più breve: (x in sum(l,[]))invece di any(x in s for s in l)entrambi xe -xrisparmia 13 byte in più!
movatica,

7

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

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)

Provalo online!

-1 byte grazie al commento di Squid sull'altra risposta di Python

Questa risposta non ha speranze di risolvere nessuno, ma il più banale dei casi di test. Nel link TIO, s*11è stato sostituito da s*2, sacrificando la correttezza in alcuni casi, per un veloce er tempo di esecuzione, ma per quanto posso vedere, la versione in questo post produce sempre la risposta corretta, in teoria.

Spiegazione

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

2
Mi fa piacere vedere che hai creato la tua risposta Python :-) Ed è anche più breve!
OOBalance,

@OOBalance Ora, se solo terminasse nella mia vita ...
ArBo,

1
Oh, mi sono dimenticato di come sia una cosa stupida con la versione di Windows (usa solo 32 bit intanche nella versione a 64 bit).
feersum

7

05AB1E , 43 41 38 35 27 byte

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

Provalo online!

Spiegazione:

.¡                              # 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

Poiché i numeri di gruppo non fanno parte dell'output, siamo liberi di utilizzare qualsiasi numero desiderato, purché l'ordine sia corretto. Questo utilizza 0 per i numeri originali, 2 ^ -N per il gruppo XN, 1 per il gruppo X, 2 per il gruppo X + 1.


3
Mi piacerebbe vedere una spiegazione di come funziona dal momento che non riesco a leggere 05AB1E.
OOBalance,

@OOBalance Ho aggiunto una spiegazione, speriamo sia abbastanza chiara.
Grimmy,

Grazie, questo lo spiega bene. Buon approccio, ho il mio voto :)
OOBalance,

2

Python 2, 195 byte

Il caso di test più lento non può essere completato su TIO , ma sulla mia macchina sono necessari solo circa 10 secondi.

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)

Può essere ridotto di 2 byte su build Python LP64 sostituendolo '%s-%%s'%a%ncon `a`+'-'+`n`.


1

JavaScript (Node.js) , 211 205 byte

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)

Provalo online!

Utilizzando il presupposto che ci siano al massimo 12 gruppi.

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

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)

Provalo 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

... o 193 byte se la restituzione di un dizionario è corretta:

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

Provalo online!

In questo caso, chiave -Infinitysignifica Gruppo 1 e altre chiavi significa Gruppo X+key.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.