Teste se determinado número se um número Keith

14

Como os números e seqüências de Fibonacci parecem um assunto popular para o código de golfe, pensei que poderia ser um desafio divertido codificar o golfe com números de Keith .

Então, proponho um desafio que é criar uma função que use um número inteiro e devolva um valor verdadeiro ou falso, dependendo do número ser um número Keith ou não.

Mais sobre os números de Keith

Em matemática de recreação, um número Keith ou um número de reconfiguração (abreviação de dígito repetitivo semelhante a Fibonacci) é um número na seguinte sequência inteira: 14, 19, 28, 47, 61, 75, 197, 742, 1104, 1537, 2208, 2580,…

Numberphile tem um vídeo explicando como calcular um número de Keith. Mas basicamente você pega os dígitos de um número. Adicione-os e, em seguida, pegue os últimos dígitos do número original e adicione-os à soma do cálculo, enxágue e repita. E exemplo para deixar claro.

14
1 + 4 = 5
4 + 5 = 9
5 + 9 = 14

Entrada

Um inteiro.

Resultado

Verdadeiro se o número for um número de Keith. Falso se não for ..

Smetad Anarkist
fonte
A rigor, "um número inteiro" pode incluir números zero ou negativos. Tenho certeza de que nenhum dos dois pode ser um número Keith. Precisamos dar conta disso?
Iszi
Dependendo da sua solução, números de um dígito podem aparecer como verdadeiros. Portanto, você deve verificar possíveis erros na entrada.
Smetad Anarkist
Tem que produzir true/ falseou pode ser qualquer coisa verdade / falsey ?
Cyoce

Respostas:

7

GolfScript ( 31 25 caracteres)

..[10base{.{+}*+(\}@*]?0>

Insira como um número inteiro no topo da pilha. A saída é 0 (falsa) ou 1 (verdadeira). Demonstração on-line que lista os números de Keith até 100.

Peter Taylor
fonte
Boa ideia com o 0>. Infelizmente, posso marcar +1 apenas uma vez.
Howard
7

Python ( 78 75)

a=input()
n=map(int,`a`)
while a>n[0]:n=n[1:]+[sum(n)]
print(a==n[0])&(a>9)

n=n[1:]+[sum(n)]faz toda a mágica. Ele pega todos os itens, exceto o primeiro item n, fica na soma de n(com o primeiro item) e depois define como n.

Eu gostaria que você pudesse chamar listum número inteiro e ter os dígitos separados.

Retorna Falseem todas as entradas abaixo de 10. Podem ser 8 caracteres menores se retornadas True.

beary605
fonte
Você pode salvar dois caracteres se comparar com e n[0]não n[-1].
28412 Howard
Economize mais cinco com print 9<a==n[0].
res
n=n[1:]+[sum(n)]pode se tornarn=n[1:]+sum(n),
Cyoce 10/10
6

GolfScript, 32 29 caracteres

...[10base\{.{+}*+(\}*]&,\9>&

Uma implementação do GolfScript que pode ser testada online . A entrada é fornecida como elemento superior na pilha e retorna 0 (ou seja, falso) ou 1, respectivamente.

Howard
fonte
@PeterTaylor Olhe para o link fornecido, onde eu fiz exatamente isso - e ele funciona ...
Howard
@ PeterTaylor Olhando para a sua solução, eu poderia reduzir ainda mais o número de caracteres na minha abordagem.
289 Howard
Devo não tiver atualizado, porque o meu comentário é aplicável a versão 1.
Peter Taylor
4

APL, 36 34 39 36 33 29 27

*+/x={(∇⍣(⊃x>¯1↑⍵))⍵,+/⍵↑⍨-⍴⍕x}⍎¨⍕x←⎕

Saída 1se Keith, 0caso contrário

GolfScript ataca novamente !!


Editar

+/x={(∇⍣(x>⊢/⍵))⍵,+/⍵↑⍨-⍴⍕x}⍎¨⍕x←⎕

Usando Redução à direita ( ⊢/) em vez de Obter menos 1 ( ¯1↑), economizando diretamente 1 caractere e indiretamente economizando 1 em Divulgar ( )

Explicação

⍎¨⍕x←⎕pega a entrada avaliada (tratada como um número) e a atribui a x. Converte-o em uma matriz de caracteres (também conhecida como "string" em outros idiomas) e percorre cada caractere (dígito), convertendo-o em um número. Portanto, isso resulta em uma matriz numérica dos dígitos.

{(∇⍣(x>⊢/⍵))⍵,+/⍵↑⍨-⍴⍕x}é a principal função do "loop":
+/⍵↑⍨-⍴⍕xpega o último ⍴⍕x(número de dígitos x) da matriz e os soma.
⍵,concatena até o final da matriz.
(x>⊢/⍵)verifique se o último número na matriz (que ainda não foi +/⍵↑⍨-⍴⍕xconcatenado) é menor que xe retorna 1ou 0
∇⍣executa essa função na nova matriz várias vezes. Portanto, se o último número for menor que x, essa função se repetirá. Caso contrário, basta retornar a nova matriz

Após a execução da função, a matriz contém as somas até o ponto em que 2 dos números são maiores ou iguais a x(por exemplo 14, gerará 1 4 5 9 14 23, 13gerará 1 3 4 7 11 18 29).
Finalmente, verifique se cada número é igual xe produza a soma do binário resultante. array.


Editar

1=+/x={(∇⍣(x>⊢/⍵))⍵,+/⍵↑⍨-⍴⍕x}⍎¨⍕x←⎕

Foram adicionados 2 caracteres :-( para gerar saída 0se a entrada for de um dígito


Mais uma edição

+/x=¯1↓{(∇⍣(x>⊢/⍵))1↓⍵,+/⍵}⍎¨⍕x←⎕

Explicação

A função agora elimina o primeiro número ( 1↓) da matriz em vez de pegar o último ⍴⍕x( ↑⍨-⍴⍕x).
No entanto, essa abordagem 1=não é adequada para lidar com números de um dígito. Agora, ele remove o último número da matriz antes de verificar a igualdade x, adicionando 1 caractere


Você adivinhou: EDITAR

+/x=1↓{1↓⍵,+/⍵}⍣{x≤+/⍵}⍎¨⍕x←⎕

Compara xcom o item recém-adicionado em vez do último item antigo; portanto x, basta soltar o primeiro (em vez do último) antes de verificar a igualdade , salvando um sinal de menos. Salva outros 3 usando outra forma do operador Power ( )

E uma resposta de 25 char gs aparece (Orz)


Última edição

x∊1↓{1↓⍵,+/⍵}⍣{x≤+/⍵}⍎¨⍕x←⎕

Não posso acreditar que perdi isso.
Não posso mais jogar golfe.

TwiNight
fonte
1
Você pode obter este até 24 caracteres: x∊{1↓⍵,+/⍵}⍣{x≤⊃⍺}⍎¨⍕x←⎕. Na função de energia, é o valor "depois".
marinus
2

Lisp comum, 134

O CL pode ser bastante ilegível às vezes.

(defun k(n)(do((a(map'list #'digit-char-p(prin1-to-string n))(cdr(nconc a(list(apply'+ a))))))((>=(car a)n)(and(> n 9)(=(car a)n)))))

Alguma formatação para evitar a rolagem horizontal:

(defun k(n)
  (do
    ((a(map'list #'digit-char-p(prin1-to-string n))(cdr(nconc a(list(apply'+ a))))))
    ((>=(car a)n)(and(> n 9)(=(car a)n)))))

Teste:

(loop for i from 10 to 1000
      if (k i)
      collect i)

=> (14 19 28 47 61 75 197 742)
daniero
fonte
1

F # - 184 caracteres

Espero que seja bom participar do meu próprio desafio.

let K n=
let rec l x=if n<10 then false else match Seq.sum x with|v when v=n->true|v when v<n->l(Seq.append(Seq.skip 1 x)[Seq.sum x])|_->false
string n|>Seq.map(fun c->int c-48)|>l

Editar Corrigido um erro referente a números pequenos.

Smetad Anarkist
fonte
É perfeitamente bom :) #
4523 beary605
Sua solução retorna true para n <10, o que eu acho que deveria ser falso.
28412 Howard
Você está certo. Eu deveria olhar para isso.
Smetad Anarkist
1

K, 55

{(x>9)&x=*|a:{(1_x),+/x}/[{~(x~*|y)|(+/y)>x}x;"I"$'$x]}

.

k)&{(x>9)&x=*|a:{(1_x),+/x}/[{~(x~*|y)|(+/y)>x}x;"I"$'$x]}'!100000
14 19 28 47 61 75 197 742 1104 1537 2208 2580 3684 4788 7385 7647 7909 31331 34285 34348 55604 62662 86935 93993
tmartin
fonte
1

PowerShell: 120 128 123 111 110 97

$j=($i=read-host)-split''|?{$_};While($x-lt$i){$x=0;$j|%{$x+=$_};$null,$j=$j+$x}$x-eq$i-and$x-gt9

$i=read-host recebe informações do usuário e as armazena em $ i.

$j=(... )-split''|?{$_}divide os dígitos de $ i em uma matriz e os armazena em $ j.

Agradecemos a Rynant por apontar que -ne''é desnecessário.

While($x-lt$i) define o seguinte loop do tipo Fibonnaci para executar até que a variável sum, $ x, atinja ou exceda $ i.

$x=0 zera $ x, para que esteja pronto para ser usado como soma (necessário para quando o loop voltar).

$j|%{$x+=$_} usa um loop ForEach-Object para adicionar os valores de $ j em $ x.

$null,$j=$j+$x muda os valores em $ j restantes, descartando o primeiro, acrescentando $ x.

Yay! Finalmente descobri uma maneira mais curta de mudar e acrescentar, e consegui esse script abaixo de 100!

$x-eq$i após a conclusão do loop while, testa se o valor da soma, $ x, é igual ao valor inicial, $ i - geralmente indicativo de um número de Keith.

-and$x-gt9 invalida números de um dígito, zero e números negativos, que não podem ser números de Keith.

Este script é um pouco "bagunçado". Ele pode lidar com $ i e $ j normalmente, mas você precisará limpar $ x entre as execuções.

Agradecemos a Keith Hill e mjolinor por alguns métodos de dividir números em dígitos que foram usados ​​em versões anteriores deste script. Embora não estejam na versão final, eles proporcionaram uma ótima experiência de aprendizado.

Iszi
fonte
Você pode remover o -ne''para que seja justo ?{$_}.
Rynant
Obrigado @Rynant. Parece que eu também posso reduzi-lo mais substituindo $i=read-host;$j=$i-split''|?{$_}'por $j=($i=read-host)-split''|?{$_}.
Iszi
0

Ruby, 82

def keith?(x)
  l="#{x}".chars.map &:to_i
  0while(l<<(s=l.inject :+)).shift&&s<x
  (s==x)&l[1]
end

Suspeite de Python é uma ferramenta melhor para este.

histocrata
fonte
0

C, 123

k(v){
    int g[9],i,n,s,t=v;
    for(n=s=0;t;t/=10)s+=g[n++]=t%10;
    for(i=n;s<v;){
        i=(i+n-1)%n;
        t=g[i];g[i]=s;s=s*2-t;
    }
    return n>1&&s==v;
}

teste via chicote:

main(i){
    for(i=0;i<20000;i++)
        if(k(i)) printf("%d ",i);
}

dá:

14 19 28 47 61 75 197 742 1104 1537 2208 2580 3684 4788 7385 7647 7909
coelho bebê
fonte
Você pode substituir i=(i+n-1)%n;t=g[i];g[i]=s;s=s*2-t;com i+=n-1;t=g[i%n];g[i%n]=s;s+=s-t;e salvar dois caracteres.
schnaader
0

R, 116

Imitação de Python:

a=scan();n=as.numeric(strsplit(as.character(a),"")[[1]]);while(a>n[1])n=c(n[-1],sum(n));if((n[1]==a)&&(a>9))T else F
Paolo
fonte
0

Perl, 90

sub k{$-=shift;$==@$=split//,$-;push@$,eval join'+',@$[-$=..-1]while@$[-1]<$-;grep/$-/,@$}

Um exercício divertido! Eu sei que é um post antigo, mas notei que o Perl estava faltando!

Tenho certeza de que posso melhorar a maneira como construo isso, digerindo as outras respostas mais minuciosamente, por isso provavelmente revisitarei isso!

Dom Hastings
fonte
0

Smalltalk - 136 car

 [:n|s:=n asString collect:[:c|c digitValue]as:OrderedCollection.w:=s size.[n>s last]whileTrue:[s add:(s last:w)sum].^(s last=n and:n>9)]

Envie este bloco value:

Paul Richter
fonte
0

Java - 1437

import java.io.*;
class keith
{
    public int reverse(int n)
    {
        int i,c=0;
        while(n>0)
        {
            c=(c*10)+(n%10);
            n/=10;
        }
        return(c);
    }
    public int countdigit(int n)
    {
        int i,c=0;
        while(n>0)
        {
            c++;
            n/=10;
        }
        return(c);
    }
    public void keith_chk()throws IOException
    {
        BufferedReader br=new BufferedReader(
        new InputStreamReader(System.in));
        int n,digi,r,p=0,a,tot=0,i;
        System.out.print("Enter number :-");
        n=Integer.parseInt(br.readLine());
        digi=countdigit(n);

        int ar[]=new int[digi+1];
        r=reverse(n);
        while(r>0)
        {
            a=r%10;
            ar[p++]=a;
            tot=tot+a;
            r/=10;
        }
        ar[p]=tot;
        while(true)
        {
            for(i=0;i<=p;i++)
            System.out.print(ar[i]+"\t");
            System.out.println(); 
            if(tot == n)
            {
                System.out.print("Keith Number....");
                break;
            }
            else if(tot > n)
            {
                System.out.print("Not Keith Number.....");
                break;
            }
            tot=0;
            for(i=1;i<=p;i++)
            {
                ar[i-1]=ar[i];
                tot=tot+ar[i];
            }
            ar[p]=tot;
        }
    }
}
mousami
fonte
3
Bem-vindo ao CodeGolf.SE! Uma vez que esta questão é de código-golf , você deve golf seu código (espaços em branco remover, novas linhas ...)
Vereos
0

Python3 104

#BEGIN_CODE
def k(z):
 c=str(z);a=list(map(int,c));b=sum(a)
 while b<z:a=a[1:]+[b];b=sum(a)
 return(b==z)&(len(c)>1)
#END_CODE score: 104

print([i for i in filter(k, range(1,101))])  #[14, 19, 28, 47, 61, 75]

E é uma função;)

gcq
fonte
0

Python - 116 caracteres

Não é realmente um especialista em codegolf, então aí está, minha primeira tentativa.

x=input();n=`x`;d=[int(i)for i in n];f=d[-1]
while f<x:d+=[sum(d[-len(n):])];f=d[-1]
if f==x>13:print 1
else:print 0

Faça duas alterações para uma função:

  • Mude printparareturn
  • Atribuir xpara ser o parâmetro

PS I segundo @ beary605- adicione um built-in para separar os dígitos / caracteres / o que for.

Dan the Man
fonte
0

Ruby (com OOP)

class Recreationalmathematics
def Check_KeithSequence(digit) 
    sequence,sum=digit.to_s.split(//).to_a,0
    while(sum<digit) do
        sum=0
        sequence.last(digit.to_s.size).each{|v|  sum=sum+v.to_i}
        sequence<<sum
    end 
    return (sum==digit)?"true":"false" 
end
end
test = Recreationalmathematics.new
puts test.Check_KeithSequence(197)
puts test.Check_KeithSequence(198)
beginnerProg
fonte