Soma dos dígitos 1 a 7

21

Desafio

Dado um inteiro positivo Nque é 28 ou acima, a saída uma lista de números somando para Nque os usos cada dígito 1através 7exatamente uma vez. Você pode dar como um programa ou função.

Os dígitos podem aparecer sozinhos ou concatenados, desde que você use cada um deles uma vez sem repetições. Por exemplo, [12, 34, 56, 7]é válido, como é [1, 27, 6, 4, 35]e [1234, 567], mas não é [123, 34567]ou [3, 2, 1476]. A ordem em que os números estão listados não importa.

Se Nnão puder ser feito com 1-7, não retorne ou produza nada.

Outra informação

  • Esse é o código de golfe, portanto o código mais curto em bytes da quinta-feira, 15 de outubro, vence.

  • Faça qualquer pergunta nos comentários.

  • Tudo o que eu não especificar no desafio é com você.

  • As brechas padrão não são permitidas.

Exemplos

Isso pode esclarecer qualquer confusão:

Entrada

28

Saída

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

Entrada

100

Saída

[56, 7, 4, 31, 2]

Entrada

1234567

Saída

[1234567]

Entrada

29

Saída

Nada, 29 é inválido.

Entrada

1891

Saída

[1234, 657]

Entrada

370

Saída

[15, 342, 7, 6]

Farei mais, se necessário.

Aqui está uma pasta de todos os números possíveis criados com esses sete números, cortesia de FryAmTheEggman.

The_Basset_Hound
fonte
Para que serve a saída 29?
Geobits
4
Se você deseja que a saída não seja nada, não coloque (N/A)como saída.
mbomb007
11
@LukStorms [1234566, 1]não é uma saída válida, porque 6 é repetido. Você não pode repetir números na saída.
The_Basset_Hound
2
Talvez »... uma lista de números feitos dos dígitos decimais de 1 a 7 que somam N« seja uma formulação mais clara do que a atualmente na pergunta.
Paŭlo Ebermann
3
Para uma solução de força um pouco menos bruta: isso equivale a atribuir um coeficiente de potência de 10 a cada um, de 1, ..,, 7modo que haja pelo menos tantos quantos 1sejam 10, pelo menos tantos quantos 10sejam 100e assim por diante.
Xnor

Respostas:

9

Pitão, 18 14 bytes

hfqSjkTjkS7./Q

Graças a @isaacg por jogar fora 2 bytes e abrir caminho para mais 2.

O código falhará se não produzir saída, o que faz com que nenhuma saída seja produzida.

Isso funcionará para entradas pequenas, se você for paciente o suficiente, e para entradas maiores, se houver tempo e memória suficientes.

Para verificar se o código funciona como pretendido, você pode substituí 7-lo 3por somas dos dígitos 1 a 3 . Clique aqui para uma suíte de testes.

Execuções de exemplo

$ 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

Como funciona

           ./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.
Dennis
fonte
2
Bem feito! Uma abordagem bastante inovadora. `` MS7`` é menor que r\1\8. Também @ .. 0é o mesmo que h.
Isaacg 9/10
@isaacg Thanks! Não sei bem como errei h, mas não fazia ideia de que você poderia usar Sdessa maneira. (A referência de caractere no intérprete on-line não a menciona.) jkS7Parece ser ainda mais curta, pois não preciso smais.
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:])

Uma função que pega um número e gera uma tupla semelhante 123,4567,. Sim, esta é uma tupla válida.

A idéia é gerar todas as cadeias possíveis como 43,126,7,5,que têm os dígitos 1através 7separados por vírgulas, sem duas vírgulas consecutivas. Avalie esta expressão como uma tupla e sua soma é igual n, imprima-a e termine com erro.

Para criar todas essas seqüências, rastreamos o conjunto sde caracteres a serem usados ​​e tentamos anexar cada um com uma vírgula, o que faz com que o dígito termine a entrada, ou sem, caso em que futuros dígitos concatenarão nela.

Curto-circuito é usado para verificar se sestá vazio porque a lista-comp está vazia, e que n==sum(eval(l)), nesse caso, imprimimos le terminamos com um erro ao retirar ~o Noneretornado pela impressão (obrigado pelo Sp3000 por isso.).

Acredito que no Python 3.5, dois caracteres podem ser salvos por escrito s={*'1234567'}(obrigado Sp3000).

Há alguns pequenos aborrecimentos que comem caracteres. Uma é que, no caso de laparência 1234567sem vírgulas, ela é analisada como um único número e a chamada sumgera um erro. Isso é tratado com o truque de começar lcom o elemento 0e removê-lo durante a impressão. Isso custa 6 caracteres.

A iteração csobre a vírgula e a cadeia vazia é irritantemente prolixo for c in(',',''), pois o Python 3 não permite que essa tupla fique nua. Eu gostaria que houvesse algum caractere ?que seja ignorado em números para fazer ',?'por 4 caracteres a menos, mas não parece existir esse caractere.


Método antigo:

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)

Define uma função que pega um número e imprime uma lista.

A idéia é usar a recursão para tentar todas as ramificações. As variáveis ​​track são

  • A soma restante nnecessária
  • O conjunto de dígitos srestantes para usar
  • A lista lde números feitos até agora
  • O número parcialmente formado atual p

Quando n==0e sestiver vazio, imprima le termine por erro.

Se o número parcialmente formado atual pfor diferente de zero, tente adicioná-lo à lista e removê-lo da soma restante.

Para cada dígito xque podemos usar s, tente anexá-lo pe removê-lo s.

xnor
fonte
4

Pyth, 23

#iRThfqQsiR10Ts./M.pS7q

A força bruta ingênua, online muito lenta, leva cerca de um minuto no meu computador. Usa o padrão comum "loop para sempre até a exceção" dos campos de golfe em que o acesso à lista de combinações filtrada resultante causa um erro para números impossíveis, como 29.

Saídas como uma lista pythonic, por exemplo

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

Aqui está uma pasta de todos os números 10136 que podem ser feitos dessa maneira.

FryAmTheEggman
fonte
Posso usar o link pastebin para exemplos?
The_Basset_Hound
@The_Basset_Hound Claro, vá em frente.
FryAmTheEggman # 8/15
3

Python 2.7, 178 172 169 bytes

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

Observe que as últimas três linhas devem ser recuadas com guias, mas não consigo descobrir como fazê-lo neste editor.

Edit: Achatada uma camada de aninhamento com a ajuda do Sp3000

xsot
fonte
SE retira guias infelizmente, apenas dizendo como ele está destinado a ser recuado é bom :)
SP3000
Ah, tudo bem, ainda estou descobrindo meu caminho neste site.
Xsot # 9/15
3

JavaScript (ES6), 165196

Editar Encurtado um pouco. Pode ser mais curto usando eval, mas eu gosto de ser rápido

Força bruta, vergonhosamente mais longa que a versão Pith, mas mais rápida. Teste a execução do snippet abaixo em um navegador compatível com 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>

edc65
fonte
Sem vergonha de ser mais longo por causa do idioma, eu realmente gosto de seus JS respostas, +1
FryAmTheEggman
1

Python 2, 270 268 bytes

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

Ainda trabalhando no golfe.

Isso faz um loop até que uma correspondência seja encontrada.

Zach Gates
fonte
import asraramente é necessário - você pode fazerfrom itertools import*;P=permutations
SP3000
É mais curto de usar do map(str,i)que a compreensão da lista, e você pode construir a lista r diretamente, em vez de nivelar uma lista aninhada: r=[int(''.join(map(str,i)))for j in x for i in P(x,j)]e algo semelhante para t.
Ruth Franklin
Você pode usar `n` vez de str(n), pois nnunca estará acima do número máximo máximo.
mbomb007
1

Haskell (145 bytes)

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 recursão.

Ungolfed (337 bytes):

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)]
jkabrg
fonte
0

Scala, 195 bytes

Esta não é a mais eficiente e levou mais de 15 minutos para obter a saída para 29, mas funciona

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)

Aqui está uma saída

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
JoseM
fonte
0

Ruby, 105 bytes

Força bruta! Verifica cada subconjunto de comprimentos entre 0 e 7 dos números inteiros entre 1 e 7654321 e verifica se algum deles corresponde aos nossos critérios. Você provavelmente não quer esperar que isso termine.

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

Para executar e verificar o algoritmo, você pode restringir o espaço de pesquisa substituindo 7654321pelo maior número que você sabe que estará na resposta. Por exemplo, 56 para n = 100 ou 1234 para n = 1891. Aqui está um teste deste último:

$ 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]
daniero
fonte
0 a 7 números inteiros? Você deve usar exaclty 7 inteiros: 1,2,3,4,5,6,7
edc65
@ edc65 Você quer dizer exatamente 7 dígitos . O resultado é um conjunto de números inteiros e o tamanho do conjunto depende da entrada.
Daniero 9/10/2015
Não falo Ruby, presumo que o programa funcione, mas não entendo a explicação. Se seus números inteiros forem menores que 1234567, como você obtém 7654321?
Edc65
@ edc65 Você está certo, vou ter que mudar esse número. Vou tentar explicar melhor também.
Daniero 9/10/2015