Somma delle cifre da 1 a 7


21

Sfida

Dato un intero positivo Nche è di 28 o superiore, l'output di un elenco di numeri di sommatori Nche utilizza ogni cifra 1attraverso 7esattamente una volta. Puoi dare come programma o funzione.

Le cifre possono apparire da sole o concatenate, purché si utilizzino ognuna una volta senza ripetizioni. Ad esempio, [12, 34, 56, 7]è valido così com'è [1, 27, 6, 4, 35]e [1234, 567], ma non [123, 34567]o [3, 2, 1476]. L'ordine in cui sono elencati i numeri non ha importanza.

Se Nnon può essere effettuato con 1-7, non restituisce o restituisce nulla.

Altre informazioni

  • Questo è il golf del codice, quindi vince il codice più breve in byte entro giovedì 15 ottobre.

  • Fai qualsiasi domanda nei commenti.

  • Tutto ciò che non specifica nella sfida dipende da te.

  • Le scappatoie standard non sono ammesse.

Esempi

Questi possono chiarire qualsiasi confusione:

Ingresso

28

Produzione

[1, 2, 3, 4, 5, 6, 7]

Ingresso

100

Produzione

[56, 7, 4, 31, 2]

Ingresso

1234567

Produzione

[1234567]

Ingresso

29

Produzione

Niente, 29 non è valido.

Ingresso

1891

Produzione

[1234, 657]

Ingresso

370

Produzione

[15, 342, 7, 6]

Ne farò di più se necessario.

Ecco un insieme di tutti i possibili numeri creati con questi sette numeri, per gentile concessione di FryAmTheEggman.


A cosa serve l'output 29?
Geobits,

4
Se si desidera che l'output non sia nulla, non inserire (N/A)come output.
mbomb007,

1
@LukStorms [1234566, 1]non è un output valido, perché 6 viene ripetuto. Non è possibile ripetere i numeri nell'output.
The_Basset_Hound

2
Forse »... un elenco di numeri composto dalle cifre decimali da 1 a 7 che si sommano a N« è una formulazione più chiara di quella attualmente in questione.
Paŭlo Ebermann,

3
Per una soluzione forza leggermente meno bruta: Ciò equivale ad assegnare un coefficiente di potenza-di-10 a ciascuna di 1, ..,, 7modo che ci sia almeno tanti 1's come 10' s, almeno tanti 10's come 100' s, e così via.
xnor

Risposte:


9

Pyth, 18 14 byte

hfqSjkTjkS7./Q

Grazie a @isaacg per il golf off 2 byte e spianando la strada per altri 2.

Il codice si arresta in modo anomalo se non deve produrre alcun output, il che non produce alcun output.

Questo funzionerà per input di piccole dimensioni se sei abbastanza paziente e per quelli più grandi se hai abbastanza tempo e memoria.

Per verificare che il codice funzioni come previsto, è possibile sostituirlo 7con a 3per somme di cifre da 1 a 3 . Fai clic qui per una suite di test.

L'esempio funziona

$ time pyth/pyth.py -c 'hfqSjkTjkS7./Q' <<< 28
(1, 2, 3, 4, 5, 6, 7)

real    4m34.634s
user    4m34.751s
sys     0m0.101s
$ time pyth/pyth.py -c 'hfqSjkTjkS7./Q' <<< 29 2>/dev/null

real    9m5.819s
user    9m6.069s
sys     0m0.093s

Come funziona

           ./Q    Compute all integer partitions of the input.
 f                Filter the integer partitions:
    jkT             Join the integers with empty separator.
   S                Sort the characters of the resulting string.
      jkS7          Join [1, ..., 7] with empty separator.
  q                 Check both results for equality.
                  Keep the partition of `q' returned True.
h                 Retrieve the first element of the filtered list.
                  For a non-empty list, this retrieves the solution.
                  For the empty list, it causes an error and produces no output.

2
Molto bene! Abbastanza un approccio innovativo. `` MS7`` è più corto di r\1\8. Inoltre @ .. 0è lo stesso di h.
isaacg,

@isaacg Grazie! Non sono sicuro di come mi sono perso h, ma non avevo idea che si potesse usare in Squel modo. (Il riferimento al carattere nell'interprete online non lo menziona.) jkS7Sembra essere ancora più breve, poiché non ne ho spiù bisogno .
Dennis,

5

Python 3, 109

def f(n,s=set('1234567'),l='0,'):[f(n,s-{x},l+x+c)for c in(',','')for x in s]or n-sum(eval(l))or~print(l[2:])

Una funzione che accetta un numero e genera una tupla simile 123,4567,. Sì, questa è una tupla valida.

L'idea è quella di generare tutti i possibili stringhe simili 43,126,7,5,che hanno le cifre 1attraverso 7separati da una virgola, senza due virgole consecutive. Valuta questa espressione come una tupla e la sua somma è uguale n, stampala e termina con errore.

Per costruire tutte queste stringhe, seguiamo l'insieme sdi caratteri da usare e proviamo ad appianarli ciascuno con una virgola, il che fa sì che la cifra termini la voce, o senza, nel qual caso le cifre future si concateneranno su di essa.

Il cortocircuito viene utilizzato per verificare che ssia vuoto perché l'elenco-comp è vuoto e che n==sum(eval(l)), nel qual caso stampiamo le terminiamo con un errore prendendo ~il Nonereso dalla stampa (grazie a Sp3000 per questo.).

Credo che in Python 3.5, due caratteri possano essere salvati scrivendo s={*'1234567'}(grazie a Sp3000).

Ci sono alcuni piccoli fastidi che divorano i caratteri. Uno è che, nel caso che lsembrare 1234567senza virgole, viene analizzato come un singolo numero e la chiamata sumdà un errore. Questo viene gestito con l'hacking di iniziare lcon l'elemento 0e rimuoverlo durante la stampa. Questo costa 6 caratteri.

Scorrere cla virgola e la stringa vuota è fastidiosamente prolisso for c in(',',''), poiché Python 3 non consente a questa tupla di essere nuda. Vorrei che ci fosse un carattere ?che viene ignorato in numeri da fare ',?'per 4 caratteri in meno, ma non sembra esserci un tale carattere.


Vecchio metodo:

Python 2, 117

def f(n,s={1,2,3,4,5,6,7},l=[],p=0):
 if{n,p}|s=={0}:print l;1/0
 if p:f(n-p,s,l+[p])
 for x in s:f(n,s-{x},l,p*10+x)

Definisce una funzione che accetta un numero e stampa un elenco.

L'idea è di usare la ricorsione per provare ogni ramo. Le tracce delle variabili sono

  • La somma rimanente nnecessaria
  • L'insieme di cifre srimanenti da utilizzare
  • L'elenco ldei numeri fatto finora
  • L'attuale numero parzialmente formato p

Quando n==0e sè vuoto, stampa le termina per errore.

Se il numero parzialmente formato corrente pè diverso da zero, prova ad aggiungerlo all'elenco e rimuoverlo dalla somma rimanente.

Per ogni cifra da xcui possiamo usare s, prova ad aggiungerla pe rimuoverla s.


4

Pyth, 23

#iRThfqQsiR10Ts./M.pS7q

La forza bruta ingenua, troppo lenta online, impiega circa un minuto sul mio computer. Utilizza il modello "loop per sempre fino all'eccezione" comune dei golf pyth dove l'accesso all'elenco di combinazioni filtrate risultante causa un errore per numeri impossibili, come 29.

Output come un elenco pitonico, ad es

1891
[1234, 657]
100
[1, 2, 34, 56, 7]
370
[12, 345, 6, 7]

Ecco una pasta di tutti i 10136 numeri che possono essere fatte in questo modo.


Posso usare il link pastebin per esempi?
The_Basset_Hound

@The_Basset_Hound Naturalmente, vai avanti.
FryAmTheEggman,

3

Python 2.7, 178 172 169 byte

n=input()
for i in range(8**7):
 for j in len(set('%o0'%i))/8*range(128):
    s=''
    for c in'%o'%i:s+='+'[:j%2*len(s)]+c;j/=2
    if eval(s)==n:print map(int,s.split('+'));1/0

Nota che le ultime tre righe dovrebbero essere rientrate con le schede ma non riesco a capire come farlo in questo editor.

Modifica: appiattito uno strato di annidamento con l'aiuto di Sp3000


Purtroppo SE toglie le schede, quindi dire semplicemente come deve essere rientrato va bene :)
Sp3000,

Ah, va bene, sto ancora cercando di farmi strada in questo sito
xsot,

3

JavaScript (ES6), 165 196

Modifica Abbreviato un po '. Potrebbe essere più breve usando eval, ma mi piace che sia veloce

Forza bruta, vergognosamente più lunga della versione Pith, ma più veloce. Prova a eseguire lo snippet di seguito in un browser compatibile con EcmaScript 6.

f=z=>{for(r=i=1e6;r&&++i<8e6;)for(m=/(.).*\1|[089]/.test(w=i+'')?0:64;r&&m--;t.split`+`.map(v=>r-=v,r=z))for(t=w[j=0],l=1;d=w[++j];l+=l)t+=l&m?'+'+d:d;return r?'':t}

function test() { O.innerHTML=f(+I.value) }

test()

// Less golfed

f=z=>{
  for(r=i=1e6; r&&++i<8e6;)
    for(m=/(.).*\1|[089]/.test(w=i+'')?0:64; r&&m--; t.split`+`.map(v=>r-=v,r=z))
      for(t=w[j=0],l=1;d=w[++j];l+=l)
        t+=l&m?'+'+d:d;
  return r?'':t
}
<input id=I value=28><button onclick=test()>-></button><span id=O></span>


Non mi vergogno di essere più a lungo a causa della lingua, mi piacciono molto le tue risposte JS, +1
FryAmTheEggman

1

Python 2, 270 268 byte

from itertools import*;P=permutations
x,d,f=range(1,8),[],input()
r=sum([[int(''.join(str(n)for n in i))for i in list(P(x,j))]for j in x],[])
z=1
while z:
 t=sum([[list(j)for j in P(r,z)]for i in x],[])
 v=filter(lambda i:sum(i)==f,t)
 if v:print v[0];break
 else:z+=1

Sto ancora lavorando sul golf.

Questo scorre fino a quando non viene trovata una corrispondenza.


import asè raramente necessario - puoi farlofrom itertools import*;P=permutations
Sp3000

È più breve da usare map(str,i)rispetto alla comprensione dell'elenco e puoi costruire l'elenco r direttamente anziché appiattire un elenco nidificato: r=[int(''.join(map(str,i)))for j in x for i in P(x,j)]e una cosa simile per t.
Ruth Franklin,

È possibile utilizzare `n`invece di str(n), poiché nnon sarà mai superiore all'intero massimo.
mbomb007,

1

Haskell (145 byte)

main=getLine>>=print.head.f[1..7].read
f[]0=[[]]
f b s=[n:j|(n,g)<-m b,j<-f g$s-n]
m b=[(d+10*z,g)|d<-b,(z,g)<-(0,filter(/=d)b):m(filter(/=d)b)]

Usa la ricorsione.

Ungolfed (337 byte):

delete d = filter (/= d)
main = getLine >>= print . (`form` [1..7]) . read

form s [] | s == 0    = [[]]
form s ds | s <= 0    = []
form s ds | otherwise = [n:ns | (n, ds') <- makeNumbers ds, ns <- form (s-n) ds']

makeNumbers [] = []
makeNumbers ds  = [(d + 10 * n',ds') | d <- ds, (n',ds') <- (0,delete d ds):makeNumbers (delete d ds)]

0

Scala, 195 byte

Questo non è il più efficiente e ci sono voluti più di 15 minuti per ottenere l'output per 29 ma funziona

def g(s: Seq[Int]): Iterator[Seq[Int]]=s.combinations(2).map(c=>g(c.mkString.toInt +: s.filterNot(c.contains))).flatten ++ Seq(s)
def f(i: Int)=(1 to 7).permutations.map(g).flatten.find(_.sum==i)

Ecco qualche risultato

scala> f(100)
res2: Option[Seq[Int]] = Some(Vector(46, 35, 12, 7))

scala> f(1891)
res3: Option[Seq[Int]] = Some(Vector(567, 1324))

scala> f(370)
res4: Option[Seq[Int]] = Some(Vector(345, 12, 6, 7))

scala> f(29)
res5: Option[Seq[Int]] = None

0

Rubino, 105 byte

Forza bruta! Controlla ogni sottoinsieme di lunghezze comprese tra 0 e 7 degli interi tra 1 e 7654321 e verifica se qualcuno di essi soddisfa i nostri criteri. Probabilmente non vuoi aspettare che questo termini.

->n{8.times{|i|[*1..7654321].permutation(i){|x|return x if
x.join.chars.sort==[*?1..?7]&&eval(x*?+)==n}}}

Per eseguire e verificare l'algoritmo è possibile restringere lo spazio di ricerca sostituendolo 7654321con il numero più grande che si sa sarà nella risposta. Ad esempio, 56 per n = 100 o 1234 per n = 1891. Ecco una prova di quest'ultimo:

$ ruby -e "p ->n{8.times{|i|[*1..1234].permutation(i){|x|return x if x.join.chars.sort==[*?1..?7]&&eval(x*?+)==n}}}[gets.to_i]" <<< 1891
[657, 1234]

Da 0 a 7 numeri interi? Dovresti usare esattamente 7 interi: 1,2,3,4,5,6,7
edc65

@ edc65 Intendi esattamente 7 cifre . Il risultato è un set di numeri interi e la dimensione del set dipende dall'input.
daniero,

Non parlo Ruby, presumo che il programma funzioni, ma non ho la spiegazione. Se i tuoi numeri interi sono inferiori a 1234567, come ottieni 7654321?
edc65,

@ edc65 Hai ragione, dovrò cambiare quel numero. Proverò a spiegarlo anche meglio.
daniero,
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.