パリンドローム逆転加算


19

パリンドローム逆転加算

反転加算のプロセスでは、作成された数字が回文になるまで、その逆に数字が追加されます。たとえば、68から始める場合、プロセスは次のようになります。

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

ご覧のとおり、これには回文数を得るために3つの追加が必要でした。で開始する場合は89、24の手順が必要になります(詳細はこちらで確認できます)。

回文に到達する前にとられたほとんどのステップの世界記録は261であり、これ1186060307891929990は10 118よりも大きい数を生み出します。しかし、パリンドロームを取得することができなかった数がかなりありました。これらはLychrel番号と呼ばれます

私たちはベース10で作業しているので、これらの数字が回文に決して到達しないという証拠が存在しないため、実際には候補と呼ぶことができるだけです。たとえば、10を基数とする最小のLychrel候補は196であり、10億回をはるかに超える反復を経験しています。回文が存在する場合、10 10 8.77よりもはるかに大きくなります。比較として、その数の1が原子に内接している場合、2.26772×10 588843575宇宙分の原子が必要です。

あなたのタスク

整数入力を受け取り、回文に到達するために必要なステップ数を返すか出力するプログラムまたは関数を作成します。Lychrelの候補に対処する必要はありません(つまり、Lychrelの候補が与えられると、プログラムはエラーをスローするか、永久に実行できます)。

テストケース:

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

ルール

  1. 標準的な抜け穴はありません。

ボーナス

  1. フォーマットされた各追加ステップを印刷する場合n + rev(n) = m、スコアに0.75を掛けることができます。合計は、ステップ数の前に印刷されます。
  2. 数値がLychrelの候補かどうかをコードで検出できる場合、スコアに0.85を掛けることができます。この場合、261回以上の反復を必要とするものはすべてLychrelの候補であると想定するだけで十分です。何も返さないか、正解と間違われる可能性のある数字ではないものを返します(など:0〜261の範囲にない文字列または数字)。エラーは有効な出力としてカウントされず(最大再帰深度を超えたなど)、検出には使用できません。
  3. 両方のボーナスを完了したら、0.6を掛けます。

これはなので、最小バイト数が勝ちます。


このコードスニペットは、Python 3での両方のボーナスを備えたソリューションの例を示しています。

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
*0.6ボーナスは他のボーナスの上にありますか?それともそれだけですか?
マルティセン

@Maltysenちょうど0.6。
カーデ

合計を印刷するとき、印刷する必要があります10 + 01 = 11か、10 + 1 = 11それとも私たちに任されていますか?
マーティンエンダー

3
lychrel検出器の場合、印刷でき262ますか?
マルティセン

回答:


8

Pyth、12バイト

f_I`~+Qs_`Q0

オンラインで試す:デモンストレーションまたはテストハーネス

これはまったく新しい機能を使用します(わずか17時間)。

説明

               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

編集:

コードを少し変更しました。古いバージョンは

fqKs_`Q~+QK0

同じバイトカウントですが、新しいバイトカウントの方がはるかに優れています。


スコア12のボーナス。幸運を祈ります!
デニス

@Dennisあなたの権利。それはばかげた意図でした。私が持っている最高のものは、Lychrel検出を使用した13.6です。
ジャクベ

14

Python、51

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

Python 2の場合、リテラルに付加されているstr()ため、バックティックを置き換えることはできません。Llong

スコア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)

また、スコア88 * 0.6 = 52.8のPython 3の代替バージョン:

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
これは非常識です。
カーデ

6

CJam、23 22 20.4バイト

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

コードは24バイト長で、Lychrel候補の場合は-1を出力します。

オンラインでお試しください。

使い方

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.

場合は{}#成功すると、インデックスもステップ数です。一方、配列に回文が含まれていない場合、-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;}

これは、ボックスに表示されているとおりのことを行う単純なループですが、ゴルフが追加されています。1000検出ボーナスを得るためにLychrel候補に戻ります。あまりにも印刷することができたことが判明(少なくともJavaの多くの文字そのボーナスも得られたことがわかりました。ボーナスコードなしでできることは156だったので、それだけの価値がありました。

いくつかの改行あり:

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;
}

古い回答:171 * 0.85 = 145.35バイト

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;}


サンドボックスにいる間にこれに取り組んだと思います:P ゴルフの言語が10バイト未満のスコアにならないように、プログラムの長さを基準にして設定すると思います。
ケード

ボーナスルールを更新したので、あなたの新しいスコアは145.35です:)
Kade

バイト保存、定義のために、それはそうした後、必須ではありませんの最後にセミコロンを削除s++<999
クリストファー・ワート

@ChristopherWirtどのコンパイラ/バージョンで?私はそれなしで構文エラーを与えます。
ジオビット

5

ルビー、(80 + 2)* 0.6 =〜49.2

flagsで-nl、実行

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

出力は次のようになります

 $ 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

196が指定されている場合、最初の261追加ステップを印刷してからを印刷しますnil

ここではあまりトリッキーではありません。$_(入力に初期化されている)その逆が含まれているかどうかをチェックします。これは、同じサイズであるため等しい場合にのみ可能です。そうである場合、ステップ番号を出力して終了します。そうでない場合は、追加ステップを表示して実行し、新しい値を保存します$_(残念ながらeval、表示されている文字列だけではなく、末尾の0 8進リテラルとして)。putsfalsey値を返すので、ループが継続します。


" + #{b} = "バイトを保存します。
ミッチシュワルツ

そして-l、末尾の改行なしで番号をファイルに入れてパイプで送ると、ルール内でドロップするように見えますか?
ミッチシュワルツ


4

K、25バイト

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

あまりエレガントではありません。全体の形式({monad 1}{monad 2}\x)はKの一般的な「while」ループに相当します。最初のモナドは停止条件で、2番目は引数に繰り返し適用される関数xです。最初のモナド({~x~|x})は、古典的な "is xa palindrome"句の否定です。2番目のモナドは、xとxの逆を表す文字列を連結し、評価してから、を使用して結果を文字列にキャストし$ます。

中間結果を示すサンプルの実行:

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

ボーナスの要求どおりにフォーマットされた出力を行うことは非常に不格好であり、かなりの量のコードを追加します。


4

CJam、23バイト

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

まだCJamを始めて数日しか経っていないので、私は少なくともプロの何人かと同じ範囲にいることはかなりうれしいです。:) CJamのヒントにも掲載されているMartinの文字列比較トリックを使用しました。また、文字列を逆にする方法を見つけるためのデニスのソリューションを覗きました。

説明:

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.

オンラインでテストする


4

ジュリア、129120バイト* 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)

これにより、整数を入力として受け取り、整数を返す名前のない関数が作成され、その間各ステップが出力されます。Lychrelの候補には262の戻り値があります。これを呼び出すには、名前を付けます。たとえば、f=i->...

ボーナスのみに関連するコードを省略すると、このソリューションは84バイトになることに注意してください。

Ungolfed +説明:

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

例:

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

Geobitsのおかげで2バイト節約されました!


4

CJam、24バイト

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

ここでテストしてください。

説明

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.

#文字列の不等性をチェックするために使用できる理由の詳細については、このヒントを参照してください


投稿する前に回答が表示されませんでした。これはの賢い使い方です#
デニス

2

Haskell、66 53バイト

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

使用例:

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

Haskellを使用したことはありませんが、できますr=reverse xか?これにより、2行目がに変更されf x|x==r=0|1<2=1+f(show$read x+read(r))、2バイト節約されます。
ケード

@ Vioz-:いいえ、それは不可能xです。スコープ内にないからです。ただし、f x|x==r=0 .... read(r)) where r=reverse x動作しますが、それより長くなります。
nimi

2

Clojure、94バイト

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

これはゴルフをコーディングする最初の試みなので、何か間違ったことをしていないか教えてください。

いくつかのスペースで:

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

内部関数の単純な再帰。整数%1とインデックスの2つの引数を取ります%2。もし%1回文で、インデックスが返されます。それ以外の場合、関数は合計とインクリメントされたインデックスを使用して自分自身を呼び出します。外部関数は、インデックスをゼロで初期化します。

サンプル:

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バイト

本当に言語ではありません。まだかっこいい。

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) ;
}

文字列を逆にするために使用した精巧な正規表現ベースのハック以外は、非常に簡単です。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.