Знайдіть, чи задоволений номер чи ні?


21

Щасливе число визначається наступним процесом. Починаючи з будь-якого додатного цілого числа, замініть число на суму квадратів його цифр і повторіть процес, поки число не дорівнює 1 (де воно залишиться), або воно нескінченно зациклюється на циклі, який не включає 1. Ці числа для яких цей процес закінчується в 1 - це щасливі числа, тоді як ті, що не закінчуються 1, - це нещасні числа (або сумні числа). Дано номер друку, щасливий він чи нещасний.

Sample Inputs
7
4
13

Sample Outputs
Happy
Unhappy
Happy

Примітка. Ваша програма не повинна займати більше 10 секунд для будь-якого числа нижче 1 000 000 000.

Відповіді:


8

Гольфскрипт - 34 символи

~{0\`{48-.*+}/}9*1="UnhH"3/="appy"

В основному так само , як це і це .

Причина 9 ітерацій описана в цих коментарях (це теоретично повертає правильні значення приблизно до 10^10^10^974( A001273 )).


11

Рубі, 77 символів

a=gets.to_i;a=eval"#{a}".gsub /./,'+\&**2'until a<5
puts a<2?:Happy: :Unhappy

Гаразд, тому я якось розумію, як це працює (буквально беручи кожне число, розділяючи його і додаючи квадрат кожної цифри), але що з умовою зупинки (a <5) і за допомогою (a <2) вирішити, чи це щасливо чи ні? Я не сумніваюся у валідності, лише логіці.
Містер Лама

2
Це те саме, що a <= 4і a <= 1. Якщо в циклі є 1, то він щасливий, а якщо в ньому є 4, то він не задоволений. Дивіться розділ вікіпедії про нещасний цикл. Отже, як тільки значення aдорівнює 4 або менше, він перевіряє, чи є a - результатом цього є ваша відповідь.
Кейсі

8

С - 115

char b[1<<30];a;main(n){for(scanf("%d",&n);b[n]^=1;n=a)for
(a=0;a+=n%10*(n%10),n/=10;);puts(n-1?"Unhappy":"Happy");}

Для цього використовується масив 2 30- байт (1 Гб) як растрова карта для відстеження, які числа зустрічалися в циклі. В Linux це насправді працює, і це ефективно, за умови включення перекомітування пам'яті (що зазвичай за замовчуванням). При перевиконанні сторінок масиву виділяються і нульові на вимогу.

Зауважте, що для компіляції цієї програми в Linux використовується гігабайт оперативної пам’яті.


1
Чому для цієї проблеми вам знадобиться десь близько такого обсягу пам’яті?
Пітер Олсон

1
@ Петер: Я вважаю, що підхід полягає в (наївно) вловленні циклу для будь-якого числа в дозволеному діапазоні введення від 1 до 1 000 000 000. Але я погоджуюсь, що з огляду на теорію щасливих чисел, єдина перевірка, необхідна - це чи досягається число 4, бо це єдиний цикл, який коли-небудь відбудеться.
mellamokb

Мені цікаво: чому для його компіляції потрібна стільки оперативної пам’яті?
Пітер Тейлор

1
Здається, він працює добре в Windows 7 з MSVC 10. Не споживає значного обсягу пам’яті під час компіляції і лише позначає масив у файлі сторінки (те, що звучить набагато безпечніше, ніж говорить історія, яку ви пов’язали про перевиконання пам'яті ;-)) .
Джої

1
Я люблю наївність такого підходу. І зловживання за петлями прекрасне.
dmckee


6

Гольфскрипт, 49 43 41 40 39 символів

~{0\10base{.*+}/.4>}do(!"UnhH"3/="appy"

Кожне щасливе число сходить до 1; кожне нещасне число переходить до циклу, що містить 4. Крім використання цього факту, це ледве не гольф.

(Дякую Вентеро, від рішення якого Ruby я виграв трюк і врятував 6 символів).


5

eTeX, 153

\let~\def~\E#1{\else{\fi\if1#1H\else Unh\fi appy}\end}~\r#1?{\ifnum#1<5
\E#1\fi~\s#1{0?}}~\s#1{+#1*#1\s}~~{\expandafter\r\the\numexpr}\message{~\noexpand

Називається як etex filename.tex 34*23 + 32/2 ?(включаючи знак запитання в кінці). Пробіли у виразі значення не мають.

EDIT: Я знизився до 123 , але тепер вихід є dvi (якщо компілюється з etex) або pdf (якщо компілюється з pdfetex). Оскільки TeX є мовою набору, я думаю, це справедливо.

\def~{\expandafter\r\the\numexpr}\def\r#1?{\ifnum#1<5 \if1#1H\else
Unh\fi appy\end\fi~\s#1{0?}}\def\s#1{+#1*#1\s}~\noexpand

4

Пітон - 81 символ

n=input()
while n>4:n=sum((ord(c)-48)**2for c in`n`)
print("H","Unh")[n>1]+"appy"

Деякі натхнення взяли у Вентеро та Пітера Тейлора.


2
краще робити, int(c)ніж ord(c)-48....
st0le

4

Javascript ( 94 92 87 86)

do{n=0;for(i in a){n+=a[i]*a[i]|0}a=n+''}while(n>4);alert(['H','Unh'][n>1?1:0]+'appy')

Введення забезпечується шляхом встановлення на потрібне число.

Кредити на меламокб.


Збережіть 1 char:n==4?h="Unh":n==1?h="H":a=n+""}alert(h+"appy")
mellamokb

@mella Дякую Я також поголив ще один шар, змінивши ||на |.
Пітер Олсон

Збережіть 8 символів: Видаліть n==4?h.... Змінити, щоб зробити ... під час циклу з умовою while(n>4). Тоді використовуйте замість цього остаточне твердження:alert(["H","Unh"][n>1?1:0]+"appy")
mellamokb

@Mella Clever, мені це подобається.
Пітер Олсон

@Mella n потрібно визначити до циклу while, я намагаюся придумати, як не повторитисьn=0;
Пітер Олсон,

4

Python (98, але занадто заплутаний, щоб не ділитися)

f=lambda n:eval({1:'"H"',4:'"Unh"'}.get(n,'f(sum(int(x)**2for x in`n`))'))
print f(input())+"appy"

Шлях, шлях занадто довгий, щоб бути конкурентоспроможним, але, можливо, добре для сміху. Це робить "ледачу" оцінку в Python. Дійсно досить схожий на запис Haskell зараз, коли я думаю про це, просто без жодної принади.


4

постійний струм - 47 знаків

[Unh]?[[I~d*rd0<H+]dsHxd4<h]dshx72so1=oP[appy]p

Короткий опис:

I~: Отримайте коефіцієнт та залишок при діленні на 10
d*.: Залиште квадрат.
0<H: Якщо коефіцієнт більший за 0, повторіть рекурсивно.
+: Підсумуйте значення при зменшенні рекурсивного стека.

4<h: Повторіть біт суми квадратів, поки значення перевищує 4.


4

Befunge, 109

Повертає правильні значення для 1 <= n <= 10 9 -1.

v v              <   @,,,,,"Happy"<      >"yppahnU",,,,,,,@
>&>:25*%:*\25*/:#^_$+++++++++:1-!#^_:4-!#^_10g11p

3

J, 56

'Happy'"_`('Unhappy'"_)`([:$:[:+/*:@:"."0@":)@.(1&<+4&<)

Дієслово, а не окремий сценарій, оскільки питання неоднозначне.

Використання:

   happy =: 'Happy'"_`('Unhappy'"_)`([:$:[:+/*:@:"."0@":)@.(1&<+4&<)
happy =: 'Happy'"_`('Unhappy'"_)`([:$:[:+/*:@:"."0@":)@.(1&<+4&<)
   happy"0 (7 4 13)
happy"0 (7 4 13)
Happy  
Unhappy
Happy  

3

Скала, 145 символів

def d(n:Int):Int=if(n<10)n*n else d(n%10)+d(n/10)
def h(n:Int):Unit=n match{
case 1=>println("happy")
case 4=>println("unhappy")
case x=>h(d(x))}

1
Чи не (n*n)буде коротше n*n , або пробілу не вистачає, щоб відокремити вираз if від значення else?
Пітер Тейлор

Так, я це зробив, Пітер.
користувач невідомий

Ось def h(s: String):String=if(s=="1")"H"else if(s=="4")"Unh"else h(s.map(_.asDigit).map(a=>a*a).sum+"");print(h(readLine)+"appy")
рециркуляційна

@ 6infinity8: Чому ви не опублікуєте це як нову відповідь?
користувач невідомий

Початкова посада стара; Я просто намагався покращити ваше рішення.
6infinity8

3

J (50)

'appy',~>('Unh';'H'){~=&1`$:@.(>&6)@(+/@:*:@:("."0)@":)

Я впевнений, що більш компетентний J-er, ніж я, можу зробити це ще коротшим. Я відносна новачка.

Нове та вдосконалене:

('Unhappy';'Happy'){~=&1`$:@.(>&6)@(+/@:*:@:("."0)@":)

Новіші та ще вдосконаленіші завдяки ɐɔıʇǝɥʇuʎs:

(Unhappy`Happy){~=&1`$:@.(>&6)@(+/@:*:@:("."0)@":)

1
Ви можете отримати персонаж, не розбиваючи "appy". Я думаю, ви також можете видалити круглі дужки навколо ("." 0) - прислівники зв’язуються міцніше, ніж сполучники.
Джессі Мілікан

Я не можу видалити круглі дужки навколо ("."0). Це призводить до помилки ранжування, але якщо я не розділяю "Happy" і не залишаю результат у полі, я можу зберегти персонажа.
Грегорі Хіглі

Причиною я не можу оминути дужки навколо ("."0)- це те, що сполучники застосовуються до всієї попередньої групи дієслів, до якої вони приєднані. Якщо я скажу +/@:("."0)@":, це дуже відрізняється від того +/@:"."0@:, що є насправді (+/@:".)"0@:.
Грегорі Хіглі

1
Масивний некроз, але ви можете зберегти 4 символи, замінивши 'Unhappy';'Happy'на Unhappy`Happy.
ɐɔıʇǝɥʇuʎs

@ ɐɔıʇǝɥʇuʎs Це працює, але де це документально підтверджено, що ви можете пропустити цитування рядків за допомогою `?
Грегорі Хіглі

2

Пітон (91 символ)

a=lambda b:b-1and(b-4and a(sum(int(c)**2for c in`b`))or"Unh")or"H";print a(input())+"appy"

2

Лист звичайний 138

(format t"~Aappy~%"(do((i(read)(loop for c across(prin1-to-string i)sum(let((y(digit-char-p c)))(* y y)))))((< i 5)(if(= i 1)"H""Unh"))))

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

(format t "~Aappy~%"
        (do
          ((i (read)
              (loop for c across (prin1-to-string i)
                    sum (let
                          ((y (digit-char-p c)))
                          (* y y)))))
          ((< i 5) (if (= i 1) "H" "Unh"))))

Коротше буде просто повернути "Щасливий" або "Нещасний" прямо з (do), але, можливо, це не вважатиметься цілою програмою



2

Желе , 17 байт (неконкуренто *)

* Мовний виклик після дати

D²SµÐLỊị“¢*X“<@Ḥ»

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

Як?

D²SµÐLỊị“¢*X“<@Ḥ» - Main link: n
   µÐL            - loop while the accumulated unique set of results change:
D                 -   cast to a decimal list
 ²                -   square (vectorises)
  S               -   sum
                  - (yields the ultimate result, e.g. n=89 yields 58 since it enters the
                  -  "unhappy circle" at 145, loops around to 58 which would yield 145.)
      Ị           - insignificant? (abs(v)<=1 - in this case, 1 for 1, 0 otherwise)
        “¢*X“<@Ḥ» - dictionary lookup of ["Happy", "Unhappy"] (the central “ makes a list)
       ị          - index into
                  - implicit print

1

Perl 5 - 77 байт

{$n=$_*$_ for split//,$u{$n}=$n;exit warn$/.'un'[$n==1].'happy'if$u{$n};redo}

$ n - вхідне значення


1

05AB1E , 21 байт

'ŽØs[SnOD5‹#}≠i„unì}™

Спробуйте в Інтернеті або перевірте перші 100 тестових випадків .

Пояснення:

Кожне число врешті-решт призведе до або, 1або 4, тому ми зациклюємося на невизначений час і зупинимось, як тільки число опуститься нижче 5.

'ŽØ                    '# Push string "happy"
   s                    # Swap to take the (implicit) input
    [       }           # Loop indefinitely
     S                  #  Convert the integer to a list of digits
      n                 #  Square each
       O                #  Take the sum
        D5‹#            #  If this sum is smaller than 5: stop the infinite loop
             i    }    # If the result after the loop is NOT 1:
               unì     #  Prepend string "un" to string "happy"
                       # Convert the string to titlecase (and output implicitly)

Дивіться цей 05AB1E наконечник шахти (розділ Як користуватися словником? ) , Щоб зрозуміти , чому 'ŽØце "happy".


0

C ++ 135, 2 рядки

#include<iostream>
int n,i,j;int main(){for(std::cin>>n;n>1;n=++j&999?n*n+i:0)for(i=0;n/10;n/=10)i+=n%10*(n%10);std::cout<<(n?"H":"Unh")<<"appy";}

Це модифікована версія тієї, яку я тут зробив:

/programming/3543811/code-golf-happy-primes/3545056#3545056


Що &999робити? І як це працює, якщо jцінність сміття?
Девід каже, що повернеться до Моніки

@ Dgrin91, я написав це 3 роки тому, тому не можу точно згадати, як це працює. Я думаю, що & 999 робить заяву if(j==999){n = 0;}else{n=n*n +i;}, j не повинно бути значенням сміття, глобальні символи нульово ініціалізуються.
Скотт Логан

0

Так, цей виклик має три роки; так, вона вже має відповідь переможця; але оскільки мені було нудно і зробив це для чергового виклику, я подумав, що можу поставити це тут. Сюрприз сюрприз, його довго - і в ...

Java - 280 264 байт

import java.util.*;class H{public static void main(String[]a){int n=Integer.parseInt(new Scanner(System.in).nextLine()),t;while((t=h(n))/10!=0)n=t;System.out.print(t==1?"":"");}static int h(int n){if(n/10==0)return n*n;else return(int)Math.pow(n%10,2)+h(n/10);}}

Безголівки:

import java.util.*;

class H {

    public static void main(String[] a) {
        int n = Integer.parseInt(new Scanner(System.in).nextLine()), t;
        while ((t = h(n)) / 10 != 0) {
            n = t;
        }
        System.out.print(t == 1 ? "" : "");
    }

    static int h(int n) {
        if (n / 10 == 0) {
            return n * n;
        } else {
            return (int) Math.pow(n % 10, 2) + h(n / 10);
        }
    }
}


0

Clojure, 107 97 байт

Оновлення: видалено непотрібне let прив'язування.

#(loop[v %](case v 1"Happy"4"Unhappy"(recur(apply +(for[i(for[c(str v)](-(int c)48))](* i i))))))

Оригінал:

#(loop[v %](let[r(apply +(for[i(for[c(str v)](-(int c)48))](* i i)))](case r 1"Happy"4"Unhappy"(recur r))))

Перший час використання вкладеного for: o


0

R, 117 91 байт

-16 байт завдяки Джузеппе

a=scan();while(!a%in%c(1,4))a=sum((a%/%10^(0:nchar(a))%%10)^2);`if`(a-1,'unhappy','happy')

1
Використовуйте strtoiзамість as.numericі pasteзамість as.character, але для отримання цифр існує коротший підхід . Якщо ви використовуєте `if`(a-1,"unhappy","happy")замість цього, ви повинні зберегти ще один байт. Нарешті, ви можете зробити це анонімним, щоб відголити ще кілька байтів.
Джузеппе



-1

C: 1092 символи

#include <iostream>
using namespace std ;
int main ()
{
    int m , a[25] , kan=0 , y , z=0  , n , o=0, s , k=0 , e[25]  ;
    do {
m :
        for ( int j=1 ; j <10000 ; j++ )
        {   
n:
            for (int i=0 ; j!=0 ; i++ )
            {
                a[i]=j%10 ;
                j/=10 ;
                kan++ ;
            }
            for ( int i=0 ; i<kan ; i++ )
            {
                y=a[i]*a[i] ;
                z+=y ;
            }
            k+=1 ;
            if (z==1)
            {
              cout<<j<<endl;
               o++ ;
            }

            else 
            {   
                 for (int f=0 ; f<k ; f++ )
                 {
                     e[f]=z ;
                 }
                 for ( int f=0 ; f=k-1 ; f++ )
                 {
                     for ( int p=f+1 ; p <k-1 ; p++ )
                     {
                         if(e[f]=e[p])
                             goto m ;
                         else { j=z ; goto n ; } 
                     }
                 }
            }
        }
    }while(o!=100) ;
    return 0 ;
}

6
Ласкаво просимо до головоломки програмування та коду для гольфу @jannat. Зауважте, що гольф коду - це завдання написати найкоротший можливий код. Це означає, що тут ми пишемо необмежений і майже нечитабельний код і змушуємо межі синтаксису мови скорочувати наші коди, наскільки це можливо.
манатура

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