Inverter e subtrair

22

Descrição do Desafio

Vamos pegar um número inteiro positivo n, reverter seus dígitos para obter rev(n)e obter o valor absoluto da diferença desses dois números: |n - rev(n)|(ou abs(n - rev(n))).

Exemplo:

n = 5067 
rev(n) = 7605
|n - rev(n)| = |5067 - 7605| = |-2538| = 2538

Depois de repetir essa operação várias vezes, a maioria dos números se tornará 0(terminando assim o loop) ...

5067 -> 2538 -> 5814 -> 1629 -> 7632 -> 5265 -> 360 -> 297 -> 495 -> 99 -> 0

... embora alguns números (como 1584) fiquem presos em um loop infinito:

1584 -> 3267 -> 4356 -> 2178 -> 6534 -> 2178 -> 6534 -> 2178 -> 6534 -> ...
                        ^ infinite loop starts here

Seu trabalho é determinar se um número inteiro fica preso em um loop infinito.

Descrição da entrada

Um número inteiro positivo.

Descrição da saída

Um valor verdadeiro ( True, 1) se o número ficar preso em um loop infinito, um valor falso ( False, 0) caso contrário.

Notas

  • Zeros à direita devem ser omitidos. ie rev(5020) = 205.
  • Lembre-se de que isso é , portanto, faça seu código o mais curto possível!
  • Sequência relevante: A072140
shooqie
fonte
Uma observação interessante: é possível construir um número inteiro arbitrariamente longo com um período de loop de 2, conforme descrito nos comentários em A072141 . O método é idêntico para outros períodos, tais como, 12, 14, 17, e 22.
mbomb007

Respostas:

18

Pitão, 5 bytes

4 bytes graças a FryAmTheEggman

uas_`

Suíte de teste.

O valor de verdade é um dos números no loop.

O valor de falsey é 0.

Explicação

uas_`      Input:Q
uas_`GGQ   Implicit filling of variables.

u      Q   Set G as Q: do this repeatedly until result seen before: Set G as
 a             the absolute difference of
     G             G
    `              convert to string
   _               reverse
  s                convert to integer
      G        and G
Freira Furada
fonte
Bom uso das variáveis ​​de preenchimento automático!
FryAmTheEggman
1
* abuso - - - - -
Leaky Nun
Como isso funciona, para alguém que não conhece Pyth?
Fatalize
3
como pyth é tão curto e ainda está no intervalo ASCII ._.
Downgoat
3
@ Downgoat Porque é pit.
Leaky Nun
11

Mathematica, 39 37 bytes

Nest[Abs[#-IntegerReverse@#]&,#,#]<1&

Simplesmente aplica os ntempos de transformação de reversão / subtração à entrada ne verifica se o resultado é 0. Nunca é possível 10nexecutar mais do que etapas para alcançar um loop, porque a transformação não pode aumentar o número de dígitos e há menos do que 10nnúmeros com não mais do que dígitos n. Veja a prova de Dennis para saber como reduzir esse limite n.

Martin Ender
fonte
10

Gelatina , 6 5 bytes

ṚḌạµ¡

Experimente online!

fundo

Isso usa o limite superior de 10n iterações do @ MartinEnder e as seguintes observações.

  1. Existem 9 × 10 k - 1 inteiros positivos n com k dígitos.

  2. A diferença de um número e seu reverso é sempre um múltiplo de 9 , portanto, apenas 10 k - 1 deles podem ocorrer após a primeira iteração.

  3. Dos múltiplos, mais de 1/10 perderá um dígito na próxima iteração (para iniciantes, tudo o que começa e termina com os mesmos dígitos, e aproximadamente o dobro se o primeiro dígito não é 1 nem 9 ), então são necessários no máximo 9 × 10 k - 2 para inserir um loop ou perder um dígito.

  4. Aplicando o mesmo raciocínio ao número inteiro resultante de k - 1 dígitos e assim por diante, são necessárias no máximo 9 × 10 k - 2 + 9 × 10 k - 2 +… ≤ 10 k - 1 ≤ n iterações para inserir um loop ou alcance 0 .

Como funciona

ṚḌạµ¡  Main link. Argument: n

   µ¡  Iteratively apply the chain to the left n times.
Ṛ      Reverse n (casts to digits).
 Ḍ     Undecimal; convert from base 10 to integer.
  ạ    Take the absolute difference of the result and the argument.
Dennis
fonte
11
Pyth venceu Jelly?
Leaky Nun
3
Bem, é um empate.
Dennis
Estes não são bytes.
Mik1
1
@mik Clique no link bytes no cabeçalho.
214 Dennis
5

Oracle SQL 11.2, 136 bytes

WITH v(n)AS(SELECT :1 FROM DUAL UNION ALL SELECT ABS(n-REVERSE(n||''))FROM v WHERE n>0)CYCLE n SET c TO 0 DEFAULT 1 SELECT MIN(c)FROM v;

Sem golfe

WITH v(n) AS
(
  SELECT :1 FROM DUAL
  UNION ALL
  SELECT ABS(n-REVERSE(n||''))FROM v WHERE n>0 
) CYCLE n SET c TO 0 DEFAULT 1
SELECT MIN(c)FROM v
Jeto
fonte
5

APL, 26 caracteres

0∘{⍵∊⍺:×⍵⋄(⍺,⍵)∇|⍵-⍎⌽⍕⍵}

Usamos o argumento esquerdo como acumulador dos valores que já vimos. Nós o inicializamos para "0", que é uma das duas condições de terminação. O guarda ⍵∊⍺:×⍵é lido: "o argumento certo é algo que já vimos (e inclui o zero)? Nesse caso, retorne o sinal do número, que é 1 ou 0". Caso contrário, vamos recuar chamando a nós mesmos com o valor absoluto da subtração depois de ter catenado o valor atual para o argumento esquerdo.


Uma reformulação da solução Mathematica de Martin Ender teria um clock de 21 caracteres :

 {×{|⍵-⍎⌽⍕⍵}⍣(10×⍵)⊣⍵}

Lê: "qual é o sinal do resultado após a aplicação das 10n vezes desejadas"?

lstefano
fonte
4

Python 2, 50 bytes

n=input()
exec'n=abs(n-int(`n`[::-1]));'*n
print n

Teste em Ideone .

fundo

Isso usa o limite superior de 10n iterações do @ MartinEnder e as seguintes observações.

  1. Existem 9 × 10 k - 1 inteiros positivos n com k dígitos.

  2. A diferença de um número e seu reverso é sempre um múltiplo de 9 , portanto, apenas 10 k - 1 deles podem ocorrer após a primeira iteração.

  3. Dos múltiplos, mais de 1/10 perderá um dígito na próxima iteração (para iniciantes, tudo o que começa e termina com os mesmos dígitos, e aproximadamente o dobro se o primeiro dígito não é 1 nem 9 ), então são necessários no máximo 9 × 10 k - 2 para inserir um loop ou perder um dígito.

  4. Aplicando o mesmo raciocínio ao número inteiro resultante de k - 1 dígitos e assim por diante, são necessárias no máximo 9 × 10 k - 2 + 9 × 10 k - 2 +… ≤ 10 k - 1 ≤ n iterações para inserir um loop ou alcance 0 .

Dennis
fonte
4

CJam, 15 13 bytes

ri_{_sW%i-z}*

Teste aqui.

O mesmo que minha resposta do Mathematica.

Martin Ender
fonte
3

Python, 129 120 96 bytes

Se uma exceção for capturada (normalmente a única exceção que pode ser lançada com essa função é um RuntimeError, devido à recursão infinita), imprima 1. Caso contrário, imprima o resultado, 0.

def r(n):a=abs(n-int(str(n)[::-1]));return a and r(a)
try:print(r(int(input())))
except:print(1)

Obrigado a @LeakyNun
Obrigado a @shooqie

TuxCrafting
fonte
Isso é oficialmente um abuso (bom) de recursão infinita.
Leaky Nun
return a and rev(a)
Leaky Nun
3
Não é possível obter um RuntimeError devido à recursão ser muito longa sem que seja necessariamente infinito?
Fatalize
a=[n-x,x-n][n>x]
Leaky Nun
Você pode encurtar drasticamente: def rev(n):a=abs(n-int(str(n)[::-1]));return a and rev(a). Além disso, o nome do curta método de algo (como rem vez de rev)
shooqie
3

Python, 101 98 bytes

Algoritmo de tartaruga e lebre.

Verdade é qualquer valor em loop, é Falsey 0.

g=lambda n:abs(n-int(str(n)[::-1]))
def r(n):
    t=g(n);h=g(t)
    while t-h:h=g(g(h));t=g(t)
    return h

Ideone it!

Freira Furada
fonte
3

Python 2, 85 84 83 bytes

L=[]
def f(n,L=L):
    if n<1or n in L:print n<1
    else:L+=[n];f(abs(n-int(`n`[::-1])))

Outra resposta Python. Ele adiciona n a uma lista para cada iteração e, se n já estiver na lista, ele gera False. Caso contrário, ele funcionará até 0.

Obrigado @NonlinearFruit por um byte.

atlasologist
fonte
1
Acredito print n<1obras (uma vez que né sempre não-negativo) e ele salva um byte
NonlinearFruit
def f(n,L=[]):¶ if n<1or n in L:print n<1¶ else:f(abs(n-int(`n`[::-1])),L+[n])salva 5 bytes
Freira furada
3

05AB1E, 11 8 6 bytes

DFÂï-Ä

Explicado

DF          # input number of times do
  Â         # push current number and its reverse
   ï-       # convert reverse to int and subtract
     Ä      # absolute value
            # implicitly print after loop ends

O valor de verdade é um número do loop.
O valor da falsidade é 0.

Experimente online

Usa o limite superior explicado na resposta de Dennis 'Jelly

Guardado 2 bytes graças a @Adnan

Na versão 7.9 de 05AB1E, as seguintes soluções de 5 bytes funcionam conforme observado por @Adnan

DFÂ-Ä
Emigna
fonte
Ok, isso é um pouco estranho, mas DFÂ-Äfunciona na versão 7.9, mas não na versão atual. Na versão atual, você precisa convertê-lo para um int primeiro (como este DFÂï-Ä), mas pode usar a versão 7.9 para obter 5 bytes: p.
Adnan
@ Adnan Não acredito que esqueci a função de bifurcação. Vou manter a versão atual embora. Você pode postar o 7.9 como uma resposta separada, se desejar. Caso contrário, vou colocar como uma nota.
Emigna
Provavelmente não vou publicá-lo, pois está a apenas 1 byte desta resposta: p.
Adnan
1

Java 7, 161 bytes

Isso requer uma importação, mas eu a escrevi como uma função. Grite comigo nos comentários se um programa completo for preferido nesse cenário. Produz 1 se houver um loop infinito e 0 se o valor chegar a 0.

import java.util.*;int z(int a){int o,r,c=a;Set s=new HashSet();while(c!=0){for(r=0,o=c;o!=0;r=r*10+o%10,o/=10);c=Math.abs(c-r);if(!s.add(c))return 1;}return 0;}
Cutucar
fonte
Observando que eu já vi importações e funções feitas antes. exemplo
Poke
É 1verdade?
Leaky Nun
1
O @LeakyNun 1 não é considerado verdade em java, mas as listas OP (True, 1) e (False, 0) como saídas aceitáveis.
Puxa
@LeakyNun Java ainda tem um senso de verdade ou falsidade?
Neil
@Neil Java tem um sentido de alavancar oportunidades de sinergia em contextos de mercado vertical - é isso
cat
1

Brachylog , 49 32 23 bytes

:10*N,?:N:{r:?-+.}itT'0

Retorna truepara loops infinitos e falsecaso contrário.

Esta é uma adaptação vergonhosa do algoritmo de Martin Ender.

Resposta anterior, 32 bytes

g{tTr:T-+U(0!\;?:ImU;?:[U]c:1&)}

Explicação da resposta anterior

g{                             } Call predicate with [Input] as input
  tT                             T is the last element of Input
    r:T-                         Subtract T from the reverse of T
        +U                       U is the absolute value of T
          (0!\                   If U is 0, return false
              ;                  Or
               ?:ImU             If U is in Input, return true
                    ;            Or
                     ?:[U]c:1&)  Recursive call with U concatenated to the Input
Fatalizar
fonte
0

PowerShell v2 +, 94 bytes

param($n)for($a=,0;){if(($n=[math]::Abs($n-(-join"$n"["$n".length..0])))-in$a){$n;exit}$a+=$n}

Recebe entrada $n, inicia um forloop infinito , com $a=,0como condição inicial (isso usa o operador de vírgula para definir $auma matriz de um elemento 0). Este $aé o nosso conjunto de valores já vistos.

Cada iteração de loop, verificamos um if. A condição primeiro define o próximo valor do $nuso de reversão de string e a [math]::Abschamada do .NET e verifica se esse valor já está -in $a. Se sim, produzimos $ne exit. Caso contrário, adicionamos esse valor à matriz e continuamos o loop.

Saídas 0para valores de entrada em que não entra em um loop infinito (que é falsey no PowerShell) e gera o valor em que o loop foi encontrado de outra forma (números inteiros diferentes de zero são verdadeiros). Por exemplo, saídas 2178para entrada 1584.

AdmBorkBork
fonte
0

Haskell, 65 bytes

_#0=0
a#n|elem n a=1|1<2=(n:a)#abs(n-(read$reverse$show n))
([]#)

Retorna 0para Falso e 1Verdadeiro. Exemplo de uso: ([]#) 1584-> 1.

A abordagem óbvia: mantenha uma lista com todos os resultados vistos até o momento. Calcule o próximo número até 0ou esteja na lista.

nimi
fonte
0

JavaScript (ES6), 75 bytes

f=(n,...a)=>a.includes(n=n<0?-n:n)?n:f([...n+``].reverse().join``-n,n,...a)

n<0?n=-n:ne n*=n>0||-1também trabalho. O algoritmo se assemelha um pouco à resposta do PowerShell, embora essa seja uma formulação recursiva.

Neil
fonte
0

Ruby, 57 bytes

->n,*h{h[n]=n=(n-"#{n}".reverse.to_i).abs until h[n];n>0}

A matriz inicialmente vazia hrastreia valores anteriormente atingidos. Nós iteramos o número até atingirmos um valor anterior e depois verificamos o valor na última iteração. Como 0 é um ciclo de 1, será 0 se e somente se não houver um ciclo maior. Tomo 2 bytes extras para converter isso em um booleano porque 0 é verdade em Ruby.

histocrata
fonte
0

Perl 6  58 53 33  30 bytes

sub {$/=%;$^a,{return ?1 if $/{$_}++;abs $_-.flip}...0;?0}
{$/=%;?($_,{last if $/{$_}++;abs $_-.flip}...0)[*-1]}
{?($_,{abs $_-.flip}...0)[10**$_]}

{?($_,{abs $_-.flip}...0)[$_]}

Explicação:

{ # block lambda with implicit parameter $_

  # coerce the following to Bool
  # ( False for Nil or 0, True otherwise )
  ?

  (

    $_, # start a sequence with the input

    # block lambda with implicit parameter $_
    # subtracts the previous value in the sequence and its reverse
    # ( .flip is short for $_.flip where a term is expected )
    { abs $_ - .flip } 

    ... # repeat that lambda
    0   # until you get 0

  # get the element indexed with the block's input
  # may be 0, Nil, or a number that is part of a repeating sequence
  )[ $_ ]
}

(conta com a observação anterior de que você só precisa fazer essa transformação na maioria das nvezes)

Brad Gilbert b2gills
fonte
0

Perl 5, 31 29 bytes

perl -pe'for$x(1..$_){$_=abs$_-reverse}'

perl -pe'eval"\$_=abs\$_-reverse;"x$_'

Ele itera n=|n-rev(n)|n vezes, então a saída é 0 se não houver loop,> 0 caso contrário. Dennis já provou que isso é suficiente.

A nova versão usa evale xrepete o operador em vez do forloop.

mik
fonte
Boa resposta e bem-vindo ao PPCG! Note-se que para Perl, opções de linha de comando deve ser incluído na sua byte-count, então isso não é bastante 30 bytes.
AdmBorkBork
@TimmyD ok, +1 por -popção, -lnão é necessário para uma única entrada
mik
0

Matlab, 89 84 bytes

n=input('');z=n;while n
z=abs(z-str2num(fliplr(num2str(z))));n=[n z]*all(n~=z);end
z

Abordagem simples - empilha todos os números e verifica se um número apareceu antes.

Explicação

n=input('');z=n;  -- take input, initiate z
while n           -- n is said to be positive
z=abs(z-str2num(fliplr(num2str(z)))) -- calculate the "reverse and substract"
n=[n z]           -- put the value at the end of the vector
       *all(n~=z) -- make the n all zeroes if z is previously in the vector (break the loop)
end
z                 -- print z (0 when not entered loop, >0 otherwise)
pajonk
fonte