Зміна-доповнення паліндром


19

Зміна-доповнення паліндром

Процес відміни-додавання - це число, яке додається до зворотного, поки створене число не стане паліндром. Наприклад, якщо ми почнемо з 68, процес буде таким:

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

Як бачите, для отримання паліндромного числа знадобилося 3 доповнення. Якби ми почали з цього 89, нам знадобиться 24 кроки (які ви можете побачити тут ).

Світовий рекорд для більшості кроків, досягнутих до досягнення паліндрому, становить 261, що виникає для числа 1186060307891929990, що дає число, що перевищує 10 118 . Однак було досить багато номерів, які ми не змогли отримати паліндром. Вони називаються числами Ліхреля .

Оскільки ми працюємо в базі 10, ми дійсно можемо називати їх лише кандидатами, оскільки не існує доказів того, що ці цифри ніколи не досягають паліндром. Наприклад, найменший кандидат-ліхрель-10 - це 196, і він пройшов понад мільярд ітерацій. Якщо паліндром існує, він значно більший за 10 10 8,77 . Для порівняння: якби стільки 1с було вписано на атоми, нам знадобиться 2,26772 × 10 588843575 всесвітів, варті атомів, щоб виписати його, припускаючи, що він існує.

Ваше завдання

Створіть програму або функцію, яка займає цілим числом і повертає або роздруковує кількість кроків, необхідних для досягнення паліндром. Від вас не буде потрібно мати справу з кандидатами в Ліхрел (тобто, ваша програма, коли дається кандидату Ліхрелу, дозволена або кинути помилку, або запуститись назавжди).

Випробування:

                  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. Якщо ваш код може визначити, чи є число кандидатом Ліхрела, ви можете помножити свій результат на 0,85 . У цьому випадку достатньо припустити, що кандидат, що займає більше 261 ітерації, є кандидатом Ліхреля. Або не повертайте нічого, або все, що не є числом, яке можна помилково прийняти за правильну відповідь (тощо: будь-який рядок або число не в діапазоні 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
Чи можу я роздрукувати детектор ліхрелу 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 Ваше право. Це був смішний намір. Найкраще, що я маю, це 13,6 за допомогою виявлення Ліхреля.
Якубе

14

Пітона, 51

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

Для Python 2, backticks не може замінити str()через Lдодані до longлітералів.

Ось альтернативна версія з оцінкою 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)

І альтернативна версія для Python 3 з оцінкою 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
Це просто божевільно .. приємна робота!
Кейд

6

CJam, 23 22 20,4 байт

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

Код довжиною 24 байти і друкує -1 для кандидатів у Lychrel.

Спробуйте в Інтернеті.

Як це працює

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

Ява, 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 Я переосмислюю суму бонусів, оскільки зрозумів, що навіть у Python (порівняно лаконічна мова порівняно з C # / Java) бонуси не допомагають. Я думаю, що я зроблю це відносно тривалості програми, щоб мови для гри в гольф не закінчувались оцінкою <10 байт.
Кейд

Я оновив правила бонусу, тому ваш новий рахунок - 145,35 :)
Каде

Збережіть байт, видаліть крапку з комою в кінці визначення, це не потрібно, тому післяs++<999
Крістофер Вірт

@ChristopherWirt У якому компіляторі / версії? Шахта видає синтаксичну помилку без неї.
Геобіц

5

Рубі, (80 + 2) * 0,6 = ~ 49,2

З прапорами -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 як вісімковий буквал). putsповертає значення фальси, тому цикл продовжується.


" + #{b} = "зберігає байт.
Мітч Шварц

І, як здається, у правилах випаде, -lякщо ми помістимо число у файл без зворотнього нового рядка і передамо його?
Мітч Шварц


4

К, 25 байт

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

Не дуже елегантний. Загальна форма ( {monad 1}{monad 2}\x) є еквівалентом K загального циклу "while", де перша монада є умовою зупинки, а друга - ітеративно застосованою функцією до аргументу x. Перша монада ( {~x~|x}) - це заперечення класичної фрази "є xa palindrome". Друга монада поєднує разом рядок, що представляє х плюс зворотну частину х, оцінює його і потім передає результат назад у рядок з $.

Вибірка проб, що показує проміжні результати:

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

Виконання відформатованого виходу за запитом на отримання бонусу було б дуже незграбним і додало б значну кількість коду.


4

CJam, 23 байти

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

Ще лише кілька днів в CJam, тому я досить радий бути принаймні в тому ж діапазоні, що і деякі плюси. :) Я використовував фокус порівняння рядків Мартіна, який він також розмістив у підказках CJam. Я також зазирнув у рішення Денніса, щоб зрозуміти, як повернути рядок.

Пояснення:

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

Джулія, 129 120 байт * 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 байти.

Недоліки + пояснення:

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

Збережено 2 байти завдяки Geobits!


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? Це змінило б ваш другий рядок 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працювали б, але це довше.
німі

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. Якщо%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) ;
}

Досить просто, окрім розробленого хакера на основі регулярних виразів, який я використовував для перетворення рядка.


1

Рубі, 44

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

Для ->синтаксису лямбда потрібен Ruby 1.9 або вище .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.