ค้นหาว่าตัวเลขมีความสุขหรือไม่?


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

Ruby, 77 ตัวอักษร

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

โอเคฉันก็เลยเข้าใจว่ามันทำงานอย่างไร (เอาตัวอักษรแต่ละตัวแยกออกแล้วบวกสแควร์ของแต่ละหลัก) แต่สิ่งที่มีเงื่อนไขการหยุดของ (a <5) และการใช้ (a <2) เพื่อตัดสินใจว่ามันมีความสุขหรือไม่ หรือไม่? ฉันไม่ได้ถามคำถามที่ถูกต้องเพียงตรรกะ
Mr. Llama

2
ที่เป็นเช่นเดียวกับและa <= 4 a <= 1หากรอบมี 1 ในนั้นก็มีความสุขและถ้ามี 4 ในนั้นก็ไม่มีความสุข ดูส่วนวิกิพีเดียเกี่ยวกับวงจรที่ไม่มีความสุข ดังนั้นเมื่อค่าaเป็น 4 หรือน้อยกว่าเขาตรวจสอบว่าเป็น - ผลของการที่เป็นคำตอบของคุณ
Casey

8

C - 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ไบต์ (1GB) เป็นบิตแมปเพื่อติดตามว่ามีตัวเลขใดบ้างที่พบในวงรอบ บน Linux นี่ใช้งานได้จริงและมีประสิทธิภาพดังนั้นหากเปิดใช้งานการเขียนทับหน่วยความจำมากเกินไป (ซึ่งโดยปกติจะเป็นค่าเริ่มต้น) ด้วย overcommitting หน้าของอาร์เรย์จะถูกจัดสรรและเป็นศูนย์ตามความต้องการ

โปรดทราบว่าการรวบรวมโปรแกรมนี้บน Linux ใช้หน่วยความจำกิกะไบต์


1
เหตุใดคุณจึงต้องใช้หน่วยความจำใกล้เคียงกับปัญหานี้
Peter Olson

1
@ Peter: ฉันคิดว่าวิธีการคือ (ไร้เดียงสา) จับรอบสำหรับตัวเลขใด ๆ ในช่วงอินพุตที่ได้รับอนุญาตจาก 1 ถึง 1,000,000,000 แต่ฉันเห็นด้วยว่าในแง่ของทฤษฎีจำนวนแฮปปี้การตรวจสอบที่จำเป็นเท่านั้นคือถ้าถึงหมายเลข 4 เพราะนั่นเป็นวงจรเดียวที่จะเกิดขึ้น
mellamokb

ฉันอยากรู้ว่า: ทำไมการรวบรวมมันจึงต้องใช้แรมมาก?
ปีเตอร์เทย์เลอร์

1
ดูเหมือนว่าจะทำงานได้ดีบน Windows 7 ที่มี MSVC 10 อย่าใช้หน่วยความจำที่มีชื่อเสียงในขณะที่รวบรวมและทำเครื่องหมายเฉพาะอาร์เรย์ในไฟล์หน้า (สิ่งที่ฟังดูปลอดภัยกว่าเรื่องราวที่คุณเชื่อมโยงเกี่ยวกับ .
Joey

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

Python - 81 ตัวอักษร

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

แรงบันดาลใจบางส่วนนำมาจาก Ventero และ Peter Taylor


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')

อินพุตถูกจัดเตรียมโดยการตั้งค่า a ตามจำนวนที่ต้องการ

เครดิตเพื่อ mellamokb


ประหยัด 1 ถ่าน:n==4?h="Unh":n==1?h="H":a=n+""}alert(h+"appy")
mellamokb

@ mella ขอบคุณ ฉันยังโกนถ่านอีกโดยการเปลี่ยนไป|| |
Peter Olson

บันทึก 8 ตัวอักษร: n==4?h...ลบ การเปลี่ยนแปลงที่จะทำ ... while(n>4)ในขณะที่วงที่มีสภาพ จากนั้นใช้ข้อความสั่งสุดท้ายนี้แทน:alert(["H","Unh"][n>1?1:0]+"appy")
mellamokb

@Mella Clever ฉันชอบมัน
Peter Olson

@Mella n จะต้องกำหนดก่อนในขณะที่ห่วงฉันพยายามที่จะคิดว่าวิธีการที่จะไม่ทำซ้ำ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-expression ออกจากelse?
Peter Taylor

ใช่ฉันทำเช่นนั้นปีเตอร์
ผู้ใช้ที่ไม่รู้จัก

นี่เป็นเวอร์ชั่นแบบ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' ฉันคิดว่าคุณสามารถลบวงเล็บ aroundd ("." 0) - คำวิเศษณ์ผูกแน่นกว่าสันธาน
Jesse Millikan

ฉันไม่สามารถลบวงเล็บ("."0)ได้ นั่นทำให้เกิดข้อผิดพลาดอันดับ แต่ถ้าฉันไม่แยก 'ความสุข' และออกจากกล่องผลลัพธ์ฉันสามารถบันทึกอักขระได้
Gregory Higley

เหตุผลที่ฉันไม่สามารถละออกจากวงเล็บ("."0)คือการใช้คำสันธานร่วมกับคำกริยาที่ใช้ก่อนหน้านี้ทั้งหมดซึ่งไม่ได้เป็นสิ่งที่ฉันต้องการ ถ้าผมบอกว่า+/@:("."0)@":นั่นคือความแตกต่างจากที่เป็นจริง+/@:"."0@: (+/@:".)"0@:
Gregory Higley

1
necro ใหญ่ แต่คุณสามารถบันทึกตัวอักษร 4 โดยการแทนที่ด้วย'Unhappy';'Happy' Unhappy`Happy
Decıʇǝɥʇuʎs

@ ɐɔıʇǝɥʇuʎsใช้งานได้ แต่มันมีเอกสารอะไรบ้างที่คุณสามารถข้ามข้อความที่อ้างถึงด้วย `ได้?
Gregory Higley


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

Jelly , 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

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เป็นค่าขยะ?
David พูดว่า Reinstate Monica

@ Dgrin91 ฉันเขียนสิ่งนี้เมื่อ 3 ปีก่อนดังนั้นฉันจำไม่ได้ว่ามันทำงานอย่างไร ฉันคิดว่า & & 999 สร้างคำสั่งif(j==999){n = 0;}else{n=n*n +i;}j ไม่ควรเป็นค่าขยะมีค่าเริ่มต้นเป็นศูนย์
Scott Logan

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);}}

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 ไบต์ขอบคุณ Giuseppe

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")แทนที่ควรบันทึกไบต์อื่น ในที่สุดคุณสามารถทำให้ไม่ระบุชื่อนี้เพื่อโกนอีกสองสามไบต์
Giuseppe



-1

C: 1,092 ตัวอักษร

#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
ยินดีต้อนรับสู่ Programming Puzzles & Code Golf, @jannat โปรดทราบว่ารหัสกอล์ฟเป็นความท้าทายของการเขียนรหัสที่สั้นที่สุดที่เป็นไปได้ นั่นหมายความว่าที่นี่เราเขียนโค้ดที่ไม่ได้คิดค้นและเกือบจะอ่านไม่ได้และบังคับให้ขีด จำกัด ของไวยากรณ์ภาษาเพื่อย่อโค้ดของเราให้สั้นที่สุด
จัดการ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.