Palindrome Reversal-Addition


19

Palindrome Reversal-Addition

Il processo di Reversal-Addition è dove un numero viene aggiunto al suo rovescio fino a quando il numero creato è un palindromo. Ad esempio, se iniziamo con 68, il processo sarebbe:

68 + 86 => 154 + 451 => 605 + 506 => 1111

Come puoi vedere, ci sono volute 3 aggiunte per arrivare a un numero palindromico. Se dovessimo iniziare 89, avremmo bisogno di 24 passaggi (che puoi vedere qui la ripartizione ).

Il record mondiale per il maggior numero di passi compiuti prima del raggiungimento di un palindromo è 261, che si verifica per il numero 1186060307891929990, producendo un numero maggiore di 10 118 . Tuttavia, ci sono stati alcuni numeri che non siamo stati in grado di ottenere un palindromo. Questi sono chiamati numeri Lychrel .

Dato che stiamo lavorando nella base 10, possiamo davvero chiamarli candidati, perché non esiste alcuna prova che questi numeri non raggiungano mai un palindromo. Ad esempio, il candidato Lychrel di base 10 più piccolo ha 196 e ha superato oltre un miliardo di iterazioni. Se il palindromo esiste, è molto più grande di 10 10 8.77 . Per fare un paragone, se quel numero di 1 fosse inscritto su atomi, avremmo bisogno di 2.26772 × 10 588843575 universi di atomi per scriverlo, supponendo che esista.

Il tuo compito

Creare un programma o una funzione che accetta un input intero e restituisce o stampa il numero di passaggi necessari per raggiungere un palindromo. Non ti verrà richiesto di trattare con i candidati Lychrel (ad esempio, il tuo programma, quando assegnato un candidato Lychrel, è autorizzato a lanciare un errore o eseguire per sempre).

Casi test:

                  f(0) => 0
                 f(11) => 0
                 f(89) => 24
                f(286) => 23
          f(196196871) => 45
         f(1005499526) => 109
f(1186060307891929990) => 261

Regole

  1. Nessuna scappatoia standard.

bonus

  1. Se stampi ogni passaggio di aggiunta, formattato n + rev(n) = m, puoi moltiplicare il tuo punteggio per 0,75 . Le somme devono essere stampate prima del numero di passaggi.
  2. Se il tuo codice è in grado di rilevare se un numero è candidato a Lychrel, puoi moltiplicare il tuo punteggio per 0,85 . In questo caso è sufficiente supporre che tutto ciò che richiede più di 261 iterazioni sia un candidato Lychrel. Non restituire nulla o qualsiasi cosa che non sia un numero che può essere scambiato per una risposta corretta (ecc .: qualsiasi stringa o un numero non compreso nell'intervallo 0-261). Qualsiasi errore non viene considerato come output valido (es. Superata la profondità massima di ricorsione) e non può essere utilizzato nel rilevamento.
  3. Se completi entrambi i bonus, moltiplica per 0,6 .

Questo è , quindi vince il numero minimo di byte.


Questo frammento di codice mostra una soluzione di esempio in Python 3 con entrambi i bonus.

def do(n,c=0,s=''):
  m = str(n)
  o = m[::-1]
  if c > 261:
    return "Lychrel candidate"
  if m == o:
    print(s)
    return c
  else:
    d = int(m)+int(o)
    s+="%s + %s = %s"%(m,o,str(d))
    return do(d,c+1,s)


1
Il *0.6bonus è in cima agli altri? O è solo quello?
Maltysen,

@Maltysen Solo lo 0.6.
Kade,

Quando si stampa le somme dovremmo stampare 10 + 01 = 11o 10 + 1 = 11o è fino a noi?
Martin Ender,

3
Per il rivelatore di lychrel, posso stampare 262?
Maltysen,

Risposte:


8

Pyth, 12 byte

f_I`~+Qs_`Q0

Provalo online: cablaggio dimostrativo o di prova

Questo utilizza una funzionalità abbastanza nuova (solo 17 ore).

Spiegazione

               implicit: Q = input number
f          0   repeat the following expression until it 
               evaluates to true and return the number of steps
         `Q       convert Q to string
        _         reverse the digits
       s          convert to int
     +Q           add Q
    ~             assign the result to Q
                  (this returns the old value of Q)
   `              convert the old value of Q to a string
 _I               and check if it's invariant under the operation reverse

modificare:

Modificato un po 'il codice. La vecchia versione era

fqKs_`Q~+QK0

Stesso numero di byte, ma quello nuovo è molto più interessante.


Bonus con un punteggio di 12. Buona fortuna!
Dennis,

@Dennis Hai ragione. Era un'intenzione ridicola. Il migliore che ho è 13.6 usando il rilevamento di Lychrel.
Jakube,

14

Python, 51

def f(n):r=int(str(n)[::-1]);return n-r and-~f(n+r)

Per Python 2, i backtick non possono essere sostituiti a str()causa del Lcollegamento along letterali.

Ecco una versione alternativa con punteggio 64 * 0,85 = 54,4 :

def f(n,c=262):r=int(str(n)[::-1]);return c*(n-r)and-~f(n+r,c-1)

E una versione alternativa per Python 3 con punteggio 88 * 0.6 = 52.8 :

def f(n,c=262):r=int(str(n)[::-1]);return c*(n-r)and-~f(n+r,print(n,'+',r,'=',n+r)or~-c)

1
Questo è semplicemente folle .. bel lavoro!
Kade,

6

CJam, 23 22 20,4 byte

ri{__sW%i+}261*]{s_W%=}#

Il codice è lungo 24 byte e stampa -1 per i candidati Lychrel.

Provalo online.

Come funziona

ri                       e# Read an integer from STDIN.
  {       }261*          e# Do the following 261 times:
   __                    e#   Push two copies of the integer on the stack.
     sW%i                e#   Cast to string, reverse and cast back to integer.
         +               e#   Add the copy and the reversed copy of the integer.
               ]         e# Wrap all 262 results in an array.
                {     }# e# Push the index of the first element such that:
                 s       e#   The string representation equals...
                  _W%=   e#   the reversed string representation.

Se ha {}#esito positivo, l'indice è anche il numero di passaggi. Se, d'altra parte, l'array non contiene un palindromo, {}#spingerà -1 .


5

Java, 200 * 0.6 = 120

import java.math.*;int f(BigInteger a){int s=-1;for(String b,c;(b=a+"").equals(c=new StringBuffer(b).reverse()+"")!=s++<999;)System.out.println(b+" + "+c+" = "+(a=a.add(new BigInteger(c))));return s;}

Questo è un semplice ciclo che fa esattamente quello che dice sulla scatola, ma con l'aggiunta di un po 'di golf. Restituisce 1000per i candidati Lychrel per ottenere il bonus di rilevazione. Si scopre che sono stato in grado di stampare per non troppo personaggi (almeno per Java) e anche di afferrare quel bonus. Il meglio che potevo fare senza il codice bonus era 156, quindi ne valeva la pena.

Con alcune interruzioni di riga:

import java.math.*;
int f(BigInteger a){
    int s=-1;
    for(String b,c;(b=a+"").equals(c=new StringBuffer(b).reverse()+"")!=s++<999;)
        System.out.println(b+" + "+c+" = "+(a=a.add(new BigInteger(c))));
    return s;
}

Vecchia risposta: 171 * 0,85 = 145,35 byte

import java.math.*;int f(BigInteger a){int s=-1;for(String b,c;(b=a+"").equals(c=new StringBuffer(b).reverse()+"")!=s++<262;)a=a.add(new BigInteger(c));return s>261?-1:s;}


Suppongo che tu abbia lavorato su questo mentre era ancora nella sandbox: P Sto ripensando gli importi dei bonus, dato che ho capito anche in Python (un linguaggio relativamente conciso rispetto a C # / Java) che i bonus non aiutano. Penso che lo farò relativamente alla lunghezza del programma in modo che le lingue del golf non finiscano con un punteggio <10 byte.
Kade,

Ho aggiornato le regole del bonus, quindi il tuo nuovo punteggio è 145.35 :)
Kade,

Salvare un byte, rimuovere il punto e virgola alla fine della definizione, non è necessario, quindi dopos++<999
Christopher Wirt,

@ChristopherWirt In quale compilatore / versione? Il mio dà un errore di sintassi senza di esso.
Geobits,

5

Rubino, (80 + 2) * 0.6 = ~ 49.2

Con le bandiere -nl, corri

p (0..261).find{$_[b=$_.reverse]||puts($_+' + '+b+' = '+$_="#{$_.to_i+b.to_i}")}

L'output è simile

 $ ruby -nl lychrel.rb 
89
89 + 98 = 187
187 + 781 = 968
968 + 869 = 1837
1837 + 7381 = 9218
9218 + 8129 = 17347
17347 + 74371 = 91718
91718 + 81719 = 173437
173437 + 734371 = 907808
907808 + 808709 = 1716517
1716517 + 7156171 = 8872688
8872688 + 8862788 = 17735476
17735476 + 67453771 = 85189247
85189247 + 74298158 = 159487405
159487405 + 504784951 = 664272356
664272356 + 653272466 = 1317544822
1317544822 + 2284457131 = 3602001953
3602001953 + 3591002063 = 7193004016
7193004016 + 6104003917 = 13297007933
13297007933 + 33970079231 = 47267087164
47267087164 + 46178076274 = 93445163438
93445163438 + 83436154439 = 176881317877
176881317877 + 778713188671 = 955594506548
955594506548 + 845605495559 = 1801200002107
1801200002107 + 7012000021081 = 8813200023188
24

Se viene specificato 196, stampa i primi 261 passaggi di aggiunta e quindi nil.

Niente di troppo complicato qui. Controlliamo se $_(che è inizializzato sull'input) contiene il suo contrario, che è possibile solo se sono uguali poiché hanno le stesse dimensioni. In tal caso, stampiamo il numero del passo ed esci, altrimenti visualizziamo ed eseguiamo il passo dell'aggiunta, memorizzando il nuovo valore $_(purtroppo non posso solo evalla stringa che sto visualizzando perché interpreta un numero invertito con uno 0 finale come un letterale ottale). putsrestituisce un valore false in modo che il ciclo continui.


" + #{b} = "salva un byte.
Mitch Schwartz,

E sembra all'interno delle regole eliminare -lse inseriamo il numero in un file senza una nuova riga finale e lo inseriamo?
Mitch Schwartz,

4

Pyth - 19 byte

Utilizza ciclo while e un contatore. Probabilmente esiste un algoritmo più piccolo di questo, ma questo è piuttosto breve.

Wnz_z=z`+szs_z=hZ;Z

Provalo online qui .


Davvero molto piccolo! Ben fatto :)
Kade,

4

K, 25 byte

#1_{~x~|x}{$. x,"+",|x}\$

Non molto elegante. La forma generale ( {monad 1}{monad 2}\x) è l'equivalente di K di un ciclo "while" generale, in cui la prima monade è la condizione di arresto e la seconda è una funzione applicata in modo iterativo all'argomento x. La prima monade ( {~x~|x}) è la negazione della classica frase "is xa palindrome". La seconda monade concatena insieme una stringa che rappresenta x più il rovescio di x, la valuta e quindi ricaccia il risultato in una stringa con $.

Una corsa di esempio che mostra risultati intermedi:

  {~x~|x}{$. x,"+",|x}\$68
("68"
 "154"
 "605"
 "1111")

Fare output formattato come richiesto per il bonus sarebbe molto goffo e aggiungerebbe una quantità significativa di codice.


4

CJam, 23 byte

Wl{\)\__W%_@#\i@i+s\}g;

Mancano ancora pochi giorni a CJam, quindi sono abbastanza felice di essere almeno nella stessa gamma di alcuni dei professionisti. :) Ho usato il trucco comparativo delle stringhe di Martin che ha anche pubblicato nei suggerimenti di CJam. Ho anche dato un'occhiata alla soluzione di Dennis per capire come invertire una stringa.

Spiegazione:

W    Initialize counter, will keep this at bottom of stack.
     Start counting at -1 because the counter will be incremented in the
     last pass through the loop, when the palindrome is detected.
l    Get input.
{    Start block of while loop.
\)\  Increment counter. Need to swap before/after because it's one below top of stack.
__   Copy current value twice. Need 3 copies in total:
       * one for reversal
       * one for comparison
       * one for addition with reverse
W%   Reverse value.
_    Copy the reverse value once because we need 2 copies:
       * one for comparison
       * one for addition with original value
@    Rotate one copy of original value to top.
#    Test for non-equality with reverse, using Martin's trick.
\i   Swap reverse value to top, and convert it to int.
@i   Rotate remaining copy of original value to top, and convert it to int.
+s   Add the values, and convert result to string.
\    Swap, so that comparison result is at top of stack for while loop test.
}g   End of while loop.
;    Current value sits at top of stack. Pop it, leaving only counter.

Provalo online


4

Julia, 129 120 byte * 0,6 = 72

i->(i=big(i);n=0;d=digits;while d(i)!=reverse(d(i))&&n<262 t=BigInt(join(d(i)));println(i," + ",t," = ",i+=t);n+=1end;n)

Questo crea una funzione senza nome che accetta un numero intero come input e restituisce un numero intero, nel frattempo stampando ogni passaggio. I candidati Lychrel hanno un valore di ritorno di 262. Per chiamare questo, dagli un nome, ad es f=i->....

Nota che omettendo il codice relativo solo ai bonus, questa soluzione sarebbe di 84 byte.

Ungolfed + spiegazione:

function f(i)
    # Convert the input to a big integer
    i = big(i)

    # Initialize a step counter to 0
    n = 0

    # While the number is not a palindrome and we haven't exceeded 261 steps...
    while digits(i) != reverse(digits(i)) && n < 262

        # Get the reverse of the integer
        # Note that we aren't using reverse(); this is because digits()
        # returns an array of the digits in reverse order.
        t = BigInt(join(digits(i)))

        # Print the step and increment i
        println(i, " + ", t, " = ", i += t)

        # Count the step
        n += 1
    end

    # Return the number of steps or 262 for Lychrel candidates
    n
end

Esempi:

julia> f(286)
286 + 682 = 968
968 + 869 = 1837
1837 + 7381 = 9218
9218 + 8129 = 17347
17347 + 74371 = 91718
91718 + 81719 = 173437
173437 + 734371 = 907808
907808 + 808709 = 1716517
1716517 + 7156171 = 8872688
8872688 + 8862788 = 17735476
17735476 + 67453771 = 85189247
85189247 + 74298158 = 159487405
159487405 + 504784951 = 664272356
664272356 + 653272466 = 1317544822
1317544822 + 2284457131 = 3602001953
3602001953 + 3591002063 = 7193004016
7193004016 + 6104003917 = 13297007933
13297007933 + 33970079231 = 47267087164
47267087164 + 46178076274 = 93445163438
93445163438 + 83436154439 = 176881317877
176881317877 + 778713188671 = 955594506548
955594506548 + 845605495559 = 1801200002107
1801200002107 + 7012000021081 = 8813200023188
23

julia> f(1186060307891929990)
(steps omitted)
261

julia> f(196)
(steps omitted)
262

julia> f(11)
0

Salvato 2 byte grazie a Geobits!


4

CJam, 24 byte

0q{__W%#}{_W%~\~+s\)\}w;

Provalo qui.

Spiegazione

0q     e# Push a zero (the counter) and read input.
{      e# While this block leaves something truthy on the stack...
  __   e#   Make two copies of the current number (as a string).
  W%   e#   Reverse the second copy.
  #    e#   Check that they are not equal.
}{     e# ... run this block.
  _W%  e#   Make a copy of the current number and reverse it.
  ~\~  e#   Evaluate both N and its reverse.
  +s   e#   Add them and turn the sum into a string.
  \)\  e#   Pull up the counter, increment it, and push it back down again.
}w
;      e# Discard the palindrome to leave the counter on the stack.

Per ulteriori informazioni sul motivo per cui è #possibile utilizzare per verificare la disuguaglianza delle stringhe, vedere questo suggerimento .


Non ho visto la tua risposta prima di pubblicare. È un uso intelligente di #.
Dennis,

2

Haskell, 66 53 byte

r=reverse.show
f x|show x==r x=0|1<2=1+f(x+read(r x))

Esempio di utilizzo:

*Main> map f [0,11,89,286,196196871,1005499526,1186060307891929990]
[0,0,24,23,45,109,261]

Non ho mai usato Haskell prima, ma saresti in grado di farlo r=reverse x? Ciò cambierebbe la tua seconda riga in f x|x==r=0|1<2=1+f(show$read x+read(r))e risparmierebbe 2 byte.
Kade,

@ Vioz-: No, non è possibile, perché xnon rientrerebbe nell'ambito. Tuttavia, f x|x==r=0 .... read(r)) where r=reverse xfunzionerebbe, ma è più lungo.
nimi,

2

Clojure, 94 byte

(fn[x](#(let[r(bigint(apply str(reverse(str %1))))] (if(= %1 r)%2(recur(+ %1 r)(inc %2))))x 0))

Questo è il mio primo tentativo di codificare il golf, quindi per favore dimmi se sto facendo qualcosa di sbagliato.

Con alcuni spazi:

(fn [x]
(#(let [r (bigint (apply str (reverse (str %1))))]
  (if (= %1 r) %2 (recur (+ %1 r) (inc %2)))) x 0))

Semplice ricorsione della funzione interna. Sono necessari due argomenti, l'intero %1e un indice %2. Se%1 è un palindromo, l'indice viene restituito. Altrimenti, la funzione si chiama con la somma e l'indice incrementato. La funzione esterna inizializza l'indice con zero.

Un campione:

repl=> ((fn[x](#(let[r(bigint(apply str(reverse(str %1))))](if(= %1 r)%2(recur(+ %1 r)(inc %2))))x 0)) 1186060307891929990)
261

1

Boost.Build, 304 byte

Non proprio una lingua. Ancora bello.

import sequence ;
import regex ;
rule r ( n ) {
m = "([0-9]?)" ;
return [ sequence.join [ sequence.reverse [ regex.match "$(m)$(m)$(m)$(m)$(m)$(m)$(m)$(m)$(m)" : $(n) ] ] : "" ] ;
}
rule x ( n ) {
i = 0 ;
while $(n) != [ r $(n) ] {
n = [ CALC $(n) + [ r $(n) ] ] ;
i = [ CALC $(i) + 1 ] ;
}
echo $(i) ;
}

Abbastanza semplice, oltre all'elaborato hack basato su regex che ho usato per invertire la stringa.


1

Ruby, 44

f=->n{n==(r=n.to_s.reverse.to_i)?0:f[n+r]+1}

Richiede Ruby 1.9 o superiore per la ->sintassi lambda.

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.