Найти, счастлив ли номер или нет?


21

Счастливое число определяется следующим процессом. Начиная с любого положительного целого числа, замените число на сумму квадратов его цифр и повторяйте процесс до тех пор, пока число не станет равным 1 (там, где оно останется), или пока оно не зациклится в цикле, который не содержит 1. Эти числа для которого этот процесс заканчивается в 1, являются счастливыми числами, в то время как те, которые не заканчиваются в 1, являются несчастными числами (или грустными числами). Учитывая число, напечатайте, будет ли он счастлив или несчастлив.

Sample Inputs
7
4
13

Sample Outputs
Happy
Unhappy
Happy

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

Ответы:


8

Golfscript - 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
@Peter: Я полагаю, что подход состоит в том, чтобы (наивно) перехватить цикл для любого числа в допустимом диапазоне ввода от 1 до 1 000 000 000. Но я согласен, что в свете счастливой теории чисел единственная необходимая проверка - это достижение числа 4, потому что это единственный цикл, который когда-либо будет происходить.
mellamokb

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

1
Кажется, работает нормально в Windows 7 с MSVC 10. Не потребляет заметного объема памяти во время компиляции и помечает только массив в файле подкачки (что звучит намного безопаснее, чем рассказ, который вы связали о чрезмерном использовании памяти ;-)) ,
Джои

1
Мне нравится наивность такого подхода. И злоупотребление петлями красиво.
dmckee


6

Golfscript, 49 43 41 40 39 символов

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

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

(Спасибо Ventero, из чьего решения на 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 ?(включая знак вопроса в конце). Пробелы в выражении не имеют значения.

РЕДАКТИРОВАТЬ: я снизился до 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 символ: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 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

DC - 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?
Питер Тейлор

Да, я так и сделал, Питер.
пользователь неизвестен

Вот хвостовая рекурсивная версия на 126 байтов без сопоставления с образцом: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: Почему бы тебе не опубликовать это как новый ответ?
пользователь неизвестен

Начальный пост старый; Я просто пытался улучшить ваше решение.
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
Вы можете получить характер, не выделяя «аппи». Я думаю, что вы также можете убрать круглые скобки вокруг ("." 0) - наречия связывают крепче, чем союзы.
Джесси Милликен

Я не могу убрать круглые скобки ("."0). Это приводит к ошибке ранга, но если я не разделю «Happy» и оставлю результат в рамке, я могу сохранить символ.
Грегори Хигли,

Причина, по которой я не могу опустить круглые скобки, ("."0)состоит в том, что союзы относятся ко всему предшествующему ряду глаголов, к которым они присоединены, а это не то, что я хочу. Если я скажу +/@:("."0)@":, это очень отличается от того +/@:"."0@:, что на самом деле (+/@:".)"0@:.
Грегори Хигли

1
Огромный некро, но вы можете сохранить 4 символа, заменив 'Unhappy';'Happy'на Unhappy`Happy.
ɐɔı atuʎs 15.12.14

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


2

Common Lisp 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"))))

Короче просто вернуть «Happy» или «Unhappy» прямо из (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

Да, эта задача имеет три года; да, у него уже есть ответ победителя; но так как мне было скучно и я сделал это для другого испытания, подумал, что мог бы поставить его здесь. Сюрприз-сюрприз, его долго - и в ...

Ява - 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);}}

Ungolfed:

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

C # 94 байта

int d(int n)=>n<10?n*n:(d(n%10)+d(n/10));string h(int n)=>n==1?"happy":n==4?"unhappy":h(d(n));

Для любого заданного числа (как int), h()вернется правильное значение. Вы можете попробовать код на .NetFiddle .

Престижность пользователю неизвестен по оригинальному алгоритму .


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
Добро пожаловать в Программирование Пазлов и Code Golf, @jannat. Обратите внимание, что Code Golf - это задача написания кратчайшего кода. Это означает, что здесь мы пишем неиспользуемый и почти нечитаемый код и навязываем ограничения синтаксиса языка, чтобы максимально сократить наши коды.
manatwork

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.