Плюс і Times, Ones і Nines


18

Реалізуйте це відношення повторення як функцію або програму, яка вводить і виводить невід'ємне ціле число:

  • F (0) = 0

  • F (N) = найменше ціле число, більше F (N-1), таким чином, що сума та / або добуток його базових 10 цифр дорівнює N

N - це вхід вашої програми, а F (N) - її вихід.

Щоб було зрозуміло, сума цифр у такому числі, як 913, дорівнює 9 + 1 + 3 = 13. Виріб дорівнює 9 × 1 × 3 = 27. Для одноцифрових чисел сума і добуток - це те саме число. Числа, що містять 0, звичайно, мають товар 0.

Результати через F (70):

N F(N)
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 19
11 29
12 34
13 49
14 59
15 69
16 79
17 89
18 92
19 199
20 225
21 317
22 499
23 599
24 614
25 799
26 899
27 913
28 1147
29 2999
30 3125
31 4999
32 5999
33 6999
34 7999
35 8999
36 9114
37 19999
38 29999
39 39999
40 41125
41 59999
42 61117
43 79999
44 89999
45 91115
46 199999
47 299999
48 311128
49 499999
50 511125
51 699999
52 799999
53 899999
54 911116
55 1999999
56 2111147
57 3999999
58 4999999
59 5999999
60 6111125
61 7999999
62 8999999
63 9111117
64 11111188
65 29999999
66 39999999
67 49999999
68 59999999
69 69999999
70 71111125

Виграє найкоротший код у байтах. Кудо, якщо ви можете показати, що ваш код використовує певну ефективність.



1
Не зовсім правильна послідовність.
Захоплення Кальвіна

Відповіді:


4

05AB1E , 20 12 байт

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

µNSDOsP‚¾>å½

Використовує кодування CP-1252 . Спробуйте в Інтернеті!


Чи потрібна перевірка довжини? Я придумав µNSDOsP‚¾>å½. Здається, працює для випадково вибраних чисел.
Доступний

@ Доступний Ах, звичайно, ти геній! Навіть не знаю, чому я це включив.
Аднан

Дивовижно, як можна раптом зменшити програму на 20 байт на 40% ...
NikoNyrh

3

Математика, 71 байт, 68 символів

±0=0;±n_:=(For[x=±(n-1),FreeQ[{+##,1##}&@@IntegerDigits@x,n],x++];x)

Всього лише на 4 байти ось версія, в якій зберігаються значення ±n:

±0=0;±n_:=(For[x=±(n-1),FreeQ[{+##,1##}&@@IntegerDigits@x,n],x++];±n=x)

З останньою версією, перш ніж оцінювати ±n, PlusMinusматиме два низьких значення:

In[2]:= DownValues@PlusMinus
Out[2]= {HoldPattern[±0] :> 0, HoldPattern[±n_] :> (For[x=±(n-1),FreeQ[{+##,1##}&@@IntegerDigits@x,n],x++];±n=x)}

Тепер якщо ми оцінимо ±20:

In[3]:= ±20
In[3]:= 225

In[4]:= DownValues@PlusMinus
Out[4]= {HoldPattern[±0] :> 0, HoldPattern[±1] :> 1, HoldPattern[±2] :> 2, HoldPattern[±3] :> 3, HoldPattern[±4] :> 4, HoldPattern[±5] :> 5, HoldPattern[±6] :> 6, HoldPattern[±7] :> 7, HoldPattern[±8] :> 8, HoldPattern[±9] :> 9, HoldPattern[±10] :> 19, HoldPattern[±11] :> 29, HoldPattern[±12] :> 34, HoldPattern[±13] :> 49, HoldPattern[±14] :> 59, HoldPattern[±15] :> 69, HoldPattern[±16] :> 79, HoldPattern[±17] :> 89, HoldPattern[±18] :> 92, HoldPattern[±19] :> 199, HoldPattern[±20] :> 225, HoldPattern[±n_] :> (For[x=±(n-1),FreeQ[{+##,1##}&@@IntegerDigits@x,n],x++];±n=x)}

Це різко прискорює майбутні обчислення, оскільки Mathematica більше не буде обчислювати значення між 0та 20рекурсивно. Збережений час є більш значним, оскільки nзбільшується:

In[5]:= Quit[]

In[1]:= ±0=0;±n_:=(For[x=±(n-1),FreeQ[{+##,1##}&@@IntegerDigits@x,n],x++];±n=x)

In[2]:= AbsoluteTiming[±60]
Out[2]= {23.0563, 6111125}

In[3]:= AbsoluteTiming[±60]
Out[3]= {9.89694*10^-6, 6111125}

Це починається з F (N - 1) замість F (N - 1) + 1; рецидив повинен суворо наростати.
LegionMammal978

2

C #, 155 159 135 байт

a=n=>{if(n<1)return 0;int i=n,s=0,p=1,N=a(n-1);for(;;){s=0;p=1;foreach(var c in++i+""){s+=c-48;p*=c-48;}if(i>N&(s==n|p==n))return i;}};

Супер неефективний, займає багато часу просто N>=14. Постарайтеся отримати більш ефективне, але довше рішення.

Гаразд, набагато краще зараз, але на 4 байти довше. Ну добре, зараз я можу зробити N<=50досить швидко. Дякую @milk за економію 24 байтів!


-2 байти на заміну на for(;;)і з передбачення foreach(var c in++i+""). -22 байти замінити int.Parse(c+"")на c-48.
молоко

2

Піт - 18 17 байт

Один байт збережено завдяки @Jakube!

Використання скорочується, щоб зробити рекурсивну річ.

uf}HsM*FBjT;hGSQZ

Тестовий сюїт .


sM*FBjT;також генерує цифру суми та добутку і на 1 байт коротше.
Якубе

@Jakube ooh приємний трюк
Maltysen

1

R, 124 112 байт

f=function(N){y=x=`if`(N-1,f(N-1),0);while(N!=prod(y)&N!=sum(y)){x=x+1;y=as.double(el(strsplit(c(x,""),"")))};x}

Виходить з ладу при N = 45, оскільки R наполягає на тому, щоб записати 10 000 як 1e + 05, що не оцінено as.numeric(), це можна виправити, використовуючи as.integer()вартість 12 байт:

f=function(N){y=x=`if`(N-1,f(N-1),0);while(N!=prod(y)&N!=sum(y)){x=x+1;y=as.double(el(strsplit(c(as.integer(x),""),"")))};x}

Будучи мовою статистичного програмування, R має дратівливі багатослівні способи поділу чисел на вектор цифр. Тим більше, що все має бути перетворено назад з рядків у числові значення явно.

12 байт збережено завдяки billywob.


1
Ви можете використовувати as.double(el(strsplit(c(x,""),"")))для розділення цілого числа на вектор його цифр. Однак ви все ще as.integer()
стикаєтеся з

О, розумний спосіб примусити х до рядка: o
JAD

Ви можете також sprintf()замість цього відформатувати ціле число в рядок без задніх нулів безпосередньо: as.double(el(strsplit(sprintf("%1.f",x),"")))і пропустити використанняas.integer()
Billywob

@ LegionMammal978 Перше, що робиться в циклі while, x=x+1і це гарантовано оцінюється один раз, тому що на початку y=F(N-1)це точно не дорівнює N.
JAD

@JarkoDubbeldam На жаль, неправильно прочитайте: P
LegionMammal978

1

JavaScript (ES6) 109 107 105 91 89 Байт

f=n=>n&&eval(`for(i=f(n-1);++i,${x="[...i+''].reduce((r,v)=>"}+r+ +v)-n&&${x}r*v)-n;);i`)



console.log(f.toString().length + 2); 
console.log(f(25));
console.log(f(13));
console.log(f(8));                                  


1

JavaScript (ES6), 84 86

Редагувати: 2 байти збережено thx @Arnauld

f=n=>eval("for(v=n&&f(n-1),p=s=n+1;s&&p-1;)[...++v+''].map(d=>(p/=d,s-=d),p=s=n);v")

Тестова примітка вище 50, вона буде використовувати занадто багато вашого процесора, натисніть "Сховати результати", щоб зупинитись, поки не буде занадто пізно

f=n=>eval("for(v=n&&f(n-1),p=s=n+1;s&&p-1;)[...++v+''].map(d=>(p/=d,s-=d),p=s=n);v")

out=x=>O.textContent=x+'\n'+O.textContent

i=0
step=_=>out(i+' '+f(i),++i,setTimeout(step,i*10))

step()
<pre id=O></pre>


Думаю, for(v=n&&f(n-1),p=s=n+1;s&&p-1;)[...++v+''].map(d=>(p/=d,s-=d),p=s=n);vслід зберегти 2 байти. Я підозрюю, що це може бути скорочено ще трохи, але я не міг цього розібратися.
Арнольд

@Arnauld Я очікую певної проблеми з повторним поділом з плаваючою комою
edc65

Наша єдина вимога полягає в тому, щоб p /= dдати точний результат, коли dнасправді дільник p. Якщо я не помиляюся, це справедливо для будь-кого d <= p <= Number.MAX_SAFE_INTEGER. Коли ми отримаємо помилки округлення з плаваючою комою p % d != 0, але це має бути безпечним.
Арнольд

@darrylyeo не дайте пропозицій, ви не спробували себе (спробуйте eval`1+1` ) (ось чому codegolf.stackexchange.com/a/52204/21348 : читайте перший коментар)
edc65

1

Математика, 67 байт

a@0=0;a@b_:=NestWhile[#+1&,a[b-1]+1,+##!=b&&1##!=b&@*IntegerDigits]

Функція, названа a. Бере число як вхід і повертає число як вихід. Натхненний попереднім рішенням Mathematica, але використовує інший циклічний механізм.


1

C, 240 байт

int f(char n){int q[19],i=19,r=n%9,j=9,*p=q,c=n/9;while(i)q[--i]=0;if(c){if(!r){r=9;c--;}q[9]=c;if(!(n%r)){n/=r;while((j-1)*(n-1)*c){if(n%j)j--;else{c--;q[9+j]++;n/=j;}}q[10]=c;if(1==n)p+=9;}while(++i<10){while(p[i]--)r=r*10+i;}}return(r);}

Намагаються використовувати деякі математичні властивості послідовності.


0

PowerShell v3 +, 114 байт

param($n)$i=,0;$l=1;1..$n|%{for(;$_-notin((($b=[char[]]"$l")-join'+'|iex)),(($b-join'*'|iex))){$l++}$i+=$l};$i[$n]

Ітеративне рішення, не з легкого способу перетворити число в суму / добуток його цифр, тому воно зовсім трохи довше, ніж відповіді JavaScript.

Здійснює введення $n, встановлює $iмасив з справедливим 0(це колекція F()та встановлюється $lрівним 1(це останнє F). Потім ми петлю вгору з 1на $n, кожна ітерація виконує forцикл.

В forумовній Loop приймає на $lATEST числа, в рядку "$l", а потім відкидає , що в якості char-array, і зберігає цей масив в змінний темпі $b. Потім ми отримуємо -joinці цифри разом з +і передаємо цю тему iex(скорочується Invoke-Expressionта схожа на eval). Крім того, ми також робимо подібне з *. Ці два числа інкапсульовані в паренах і розглядаються як аргумент масиву для -notinоператора проти поточного числа $_зовнішньої петлі (тобто forцикл працює так довго, як будь-який +і *відрізняється від $_). Тіло forпетлі просто збільшується $l++.

Після того, як ми вийшли з цього внутрішнього forциклу, ми додаємо наш додаток $lяк новий елемент $i. Після того, як ми повністю виконали цикл діапазону, ми просто розміщуємо $i[$n]на конвеєрі, і вихід неявний.

Примітка. Отримує досить повільне виконання вище 20, просто через структуру циклу. Наприклад, N=40на моїй машині займає близько двох хвилин, і я навіть не переймався тестуванням N>50.


0

Пайк, 17 байт

t.fY'Bs]~ohR{Io(e

Спробуйте тут!

Або 13 байт неконкурентоспроможні

first_nтепер додає кількість знайдених предметів плюс один у iразі використання.

Q.fY'Bs]iR{)e

Спробуйте тут!

Q.f        )  -  first_n(input, start=1)
   Y          -   digits(^)
    'Bs]      -   [sum(^), product(^)]
         R}   -   V in ^
        i     -    len(results)+1
            e - ^[-1]


0

Диво , 49 байт

f\.{0\0@(:>@(| =#1sum#0)=#1prod#0)(dp +1f -#0 1)N

Зображення ftw! Використання:

f\.{0\0@(:>@(| =#1sum#0)=#1prod#0)(dp +1f -#0 1)N}; f 10

Більш зрозумілі:

f\.{
  0\0
  @(
    find @(or = #1 sum #0) = #1 prod #0
  ) (dp + 1 (f -#0 1)) N
}

Це в основному просто слово за слово виконання специфікацій.


0

БАШ, 107 байт

зі складкою + вставка + до н.е.

for ((;n<=$1;z++)){
p(){ fold -1<<<$z|paste -sd$1|bc;}
[ `p +` = $n -o `p \*` = $n ]&&((z-->n++))
}
echo $z

0

Befunge, 101 байт

&20p>:000pv
>\1+^vp011<
| >.@>:55+%:00g+00p10g*v>10g-*
::\$_^#!:/+55p01*!`"~":<^\-g00
< |!-g02
+1< v\

Спробуйте в Інтернеті! Але зауважте, що це стане дуже повільним, як тільки ви потрапите у високі сорок. Якщо ви хочете протестувати весь діапазон, вам дійсно потрібно використовувати компілятор Befunge.

Пояснення

&20p           Read N and save for later.

>              Start of main loop; current target and test number on stack, initially 0.
:              Duplicate the test number so we can manipulate it.
000p           Initialise the sum to 0.
110p           Initialise the product to 1.

>              Start of inner loop.
:55+%:         Modulo 10 of the test number to get the first digit.
00g+00p        Add to the sum.
10g*           Multiply by the product.
:"~"`!*        If greater than 126, set to 0 to prevent overflows - it'll never match.
10p            Update the product variable.
55+/           Divide the test number by 10 to get the next digit.
:!_            If not zero, repeat the inner loop

$              Drop the zero left over from the loop.
\::00g-\10g-   Compare the sum and product with the current target.
*|             Multiply the two diffs and branch; up if no match, down if either match.
\1+^           On no match, we increment the test number and repeat the main loop.
:>20g-!|       With a match, we compare the current target with the saved N.
1+\v           If that doesn't match, increment the current target and restart main loop.
\>.@           If it does match, we've got our result; output it and exit.

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