Расстояние до четырех

13

Эта задача основана на этом видео . Я рекомендую вам посмотреть его, прежде чем пытаться решить эту проблему.

Сначала мы определим функцию. Эта функция ( OEIS ) принимает целое число n в качестве входных данных и выводит количество букв в английском представлении n (без пробелов и дефисов). Например, «три» имеет 5 букв, поэтому 3 соответствует 5.

Как показано в видео, начиная с повторения любого числа, этот процесс в конечном итоге приведет к четверке, которая будет отображаться сама на себя.

Вот грубый ориентированный график, показывающий орбиты чисел меньше 16:

  12 11
    \|      
15 2 6 1 10 14 13
  \ \|/ /  /  /
   7 3-/  8--/
    \|   /
 9 0 5--/
  \ \|
   \-4

Ваша задача состоит в том, чтобы определить количество шагов, которые предпримет число (или количество раз, которое эта функция должна быть применена к числу) до достижения четырех (т. Е. Уровня на изображенном направленном графе).

Формирование английских чисел

Вот краткое объяснение того, как нужно формировать английские слова для этой задачи:

Числа с первого по девятнадцатый:

один, два, три, четыре, пять, шесть, семь, восемь, девять, десять, одиннадцать, двенадцать, тринадцать, четырнадцать, пятнадцать, шестнадцать, семнадцать, восемнадцать, девятнадцать

Для чисел больше девятнадцати процесс выглядит следующим образом:

Если число имеет место сотен, начните с названия цифры в месте сотен и «сотни».

например

100 -> "onehundred"

Если остаток меньше двадцати, добавьте английское представление остатка.

например

714 -> "sevenhundredfourteen"

В противном случае, если цифра десятков не равна нулю, добавьте правильное представление:

2-> twenty
3-> thirty
4-> forty
5-> fifty
6-> sixty
7-> seventy
8-> eighty
9-> ninety

например

470 -> "fourhundredseventy"

Наконец, если есть одна цифра, добавьте ее представление

например

681 -> "sixhundredeightyone"

Дальнейшие положения

  • Для чисел больше ста вы должны пропустить «и» при подсчете количества букв. Например, 577 - это «пятьсот семьдесят семь», в котором 23 буквы.

  • Ваша программа должна принимать все целые числа больше 0 и меньше 1000 в качестве входных данных стандартными методами.

  • Ваша программа должна вывести количество шагов, необходимых для стандартных методов вывода.

  • Это кодгольф, поэтому выигрывает решение с наименьшим количеством байтов.

Контрольные примеры

1 -> 3
4 -> 0
7 -> 2
23 -> 5
577 -> 6
600 -> 4 
Пост Рок Гарф Хантер
источник
1
Связанный я подумал , что это боян, но я не могу найти его.
Джеймс
Что случилось с "и"? Вернее, зачем уходить и ?!
Джонатан Аллан
@JonathanAllan, потому что
Мурика

Ответы:

5

JavaScript (ES6), 106 байт

f=(n,a="03354435543668877998")=>n-4&&1+f(7*(n>99)-(-a[n/100|0]-(a[n%=100]||a[n%10])-"0066555766"[n/10|0]))

Строки, кажется, лучший способ кодировать длину, несмотря на издержки преобразования чисел.

Нил
источник
Черт возьми, это почти точно, как выглядел мой (почти опубликованный) ответ, всего на 11 байт короче.
ETHproductions
@ETHproductions Хорошо, что я отправил 16 байтов, прежде чем опубликовать его!
Нил
2

Python, с num2words, 97 113 115 94 93 92 байта

+16 байт (забыли переносы , что num2words применяется , который фактически не изменяют результатов любых из тестовых примеров, хотя 23и 577имеет дефис)
+2 байта (забыл включить f=хотя рекурсивный)
-20 байт (использование re)
-8 байты благодаря мастеру @Wheat (использование ~, заменить n!=4с n-4, и ... одна строкой импорта> _ <)
-1 байты благодаря @Cyoce (пространство с 4 and)

import re,num2words as w
f=lambda n:n-4and-~f(len(re.sub('\W|and','',w.num2words(n))))

Просто подсчитывает количество шагов; работает и для больших и отрицательных целых чисел ( \Wнаходит пробелы, запятые и дефисы в результате num2words):

>>> for test in (1,4,7,23,577,600,-1*2**96,3**96):
...     print('test: {0}  ->  {1}'.format(test, f(test)))
...
test: 1  ->  3
test: 4  ->  0
test: 7  ->  2
test: 23  ->  5
test: 577  ->  6
test: 600  ->  4
test: -79228162514264337593543950336  ->  4
test: 6362685441135942358474828762538534230890216321  ->  5

Вот последний случай, шаг за шагом:

sixquattuordecillionthreehundredsixtytwotredecillionsixhundredeightyfiveduodecillionfourhundredfortyoneundecilliononehundredthirtyfivedecillionninehundredfortytwononillionthreehundredfiftyeightoctillionfourhundredseventyfourseptillioneighthundredtwentyeightsextillionsevenhundredsixtytwoquintillionfivehundredthirtyeightquadrillionfivehundredthirtyfourtrilliontwohundredthirtybillioneighthundredninetymilliontwohundredsixteenthousthreehundredtwentyone
fourhundredfiftyone
nineteen
eight
five
Джонатан Аллан
источник
1
Разве вам не нужна f=ваша лямбда-функция
Post Rock Garf Hunter
1
Попробуйте import re,num2words as rвместо двух разных утверждений.
Пост Рок Гарф Хантер
1
n-4это то же самое, чтоn!=4
Post Rock Garf Hunter
1
@WheatWizard num2wordsесть w, reвсе еще re- обратите внимание, что оба модуля и функции называютсяnum2words
Джонатан Аллан
1
Хорошо, последний, and 1+может быть заменен на, and-~чтобы сохранить один байт
Post Rock Garf Hunter
1

Mathematica, 89 байт

Length@FixedPointList[StringLength@StringReplace[IntegerName@#,{" "->"","-"->""}]&,#]-2&

Типичный Mathematica: встроенные функции хорошие, длинные имена функций плохие. FixedPointListприменяет свой первый аргумент (функцию) ко второму аргументу до тех пор, пока ответ не изменится, перечисляя все результаты; результаты включают исходный ввод и две копии повторного вывода, следовательно, -2в конце. Встроенная математикаIntegerName пробелы и дефисы, поэтому мы должны избавиться от них вручную.

Досадно, IntegerNameно вывод содержит символ «-» (Unicode # 8208), а не обычные дефисы; вот почему это представление составляет 89 байт, а не 88. (И я не мог предшествовать приведенному выше коду с четырьмя пробелами и заставить его принимать символ Unicode - любую помощь?), так что приведенный выше код не будет работать точно правильно, если его вырезать и вставить .)

Грег Мартин
источник
1

Python 2,7, 344 216 208 байт:

x=`input()`;c=0;y=lambda v:dict(zip(range(0,10),[0]+v));l=[3,3,5,4,4,3,5,5,4];d=y(l);e=y([3,6,6,6,5,5,7,7,6]);f=y([i+7for i in l])
while x!='4':x=`sum([q[int(r)]for q,r in zip([d,e,f],x[::-1])])`;c+=1
print c

Не использует никаких внешних библиотек в отличие от других ответов Python. Принимает ввод через stdinи выводит на stdout.

Repl.it со всеми тестовыми примерами!

объяснение

Сначала создается 3 словаря, каждый из которых соединяет длину представлений английского слова каждого числа с числом, которое он представляет в закрытом интервале [1,9]в десятках и сотнях соответственно. Например, первая запись в словаре dбудет , 1:3как 1пишется oneна английском языке и имеет 3письмо.

Затем каждое место цифр в некотором строковом входе xприсваивается соответствующему словарю, после чего каждое число в каждом месте сопоставляется со своим значением в соответствующем словаре. Например, предположим, что введенный номер был 23. Место 20в десятках будет соединено со словарем e, с которым он сопоставлен 6, и 3в том месте будет соединено со словарем d, с которым оно сопоставлено 5. Эти сопоставленные цифры затем складываются вместе, чтобы представить длину английского представления числа, которое назначается xв виде строки, и, x!='4'пока продолжается цикл while, увеличивая cна1каждый раз, чтобы представить количество шагов, предпринятых до сих пор. Следовательно, 23будет соответствовать тому общему количеству шагов.11что, в свою очередь, соответствует тому, 6что будет превращаться в, 3а затем в 5и, наконец 4, в результате чего5

Наконец, после завершения цикла cвыводится stdoutзначение «Расстояние до четырех», которое в этом случае будет 5.

Р. Кап
источник
1

Джава, 556 295 байтов

Спасибо @KevinCruijssen за сохранение 261 байта

  void int(n) {int s[]={0,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,9,8,6,9,9,11,10,6,6,5,5,7,7,6};int c=0,t=(int)Math.pow(10,(int)Math.log10(n)),v=1;while(n>0){if(n/100>0)c+=(s[n/100]+7);else {if(n>0&n<25){c+=s[n];break;}else{c+=s[(n/10)+22];}}n=n%t;t=t/10;}while(c!=4){v++;c=s[c];}System.out.print(v);}


Ungolfed:

  void int(n) {

    int s[]={0,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,9,8,6,9,9,11,10,6,6,5,5,7,7,6};
     int c=0,t=(int)Math.pow(10,(int)Math.log10(n)),v=1;
         while(n>0){
            if(n/100>0)
                c+=(s[n/100]+7);
            else {if(n>0&n<25){
                c+=s[n];
            break;
            }
            else{
                c+=s[(n/10)+22];

            }
            }
            n=n%t;
            t=t/10;
        }

        while(c!=4)
        {
            v++;
        c=s[c];
        }
System.out.print(v);
}
Numberknot
источник
Я думаю, что у вас есть ошибка в вашем коде, потому что s++это невозможно для
строкового
@KevinCruijssen Я объявляю S (счетчик) как INT и STRING тоже .... Java автоматически решает, что это INT.
Numberknot
Ну, если я запустил ваш код в ideone или в моей Eclipse IDE, он потерпит неудачу, потому что у вас их два s... Кстати, вы можете сыграть в свой код довольно много, например:int c(int n){int s[]={0,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,8,8,6,9,9,11,10,6,5,5,5,7,6,6},c=0,t=(int)Math.pow(10,(int)Math.log10(n)),x=1;while(n>0)if(n/100>0)c+=s[n/100]+7;else{if(n>0&n<25){c+=s[n];break;}else c+=s[(n/10)+22];}n%=t;t/=10;}for(;c!=4;x++,c=s[c]);return x;}
Кевин Круйссен
Я в шоке ...... что случилось с моим кодом и спасибо @ KevinCruijssen .. и я исправляю это ... Еще раз спасибо.
Numberknot
Np :) Я думаю, что это может быть как-то еще в гольфе без использования if-else и взлома (но я оставлю это кому-то еще), но ваш исходный код был отличной базой для решения задачи, так что +1 от меня.
Кевин Круйссен,