Code Golf: โฟร์คือเวทมนตร์


88

ปริศนา

ปริศนาเล็ก ๆ น้อย ๆ ที่ฉันได้ยินตอนเรียนมัธยมก็เป็นแบบนี้ ...

  • ผู้ถามจะขอให้ฉันให้เบอร์เขา
  • เมื่อได้ยินตัวเลขผู้ถามจะทำการเปลี่ยนแปลงบางอย่างซ้ำ ๆ (เช่นเขาอาจพูดว่าสิบคือสาม ) จนในที่สุดก็มาถึงเลข 4 (เมื่อถึงจุดนั้นเขาจะจบด้วยสี่คือเวทมนตร์ )
  • ตัวเลขใด ๆ ที่ดูเหมือนจะเปลี่ยนเป็นเลขสี่ได้ในที่สุดไม่ว่าจะเป็นอะไรก็ตาม

เป้าหมายคือการพยายามหาฟังก์ชั่นการเปลี่ยนแปลงจากนั้นจึงสามารถสร้างปริศนานี้ได้อย่างน่าเชื่อถือด้วยตัวคุณเอง

การแก้ไขปัญหา

ฟังก์ชันการเปลี่ยนแปลงในทุกขั้นตอนคือ

  • รับหมายเลขที่มีปัญหา
  • นับจำนวนตัวอักษรในการแทนคำภาษาอังกฤษโดยไม่สนใจยัติภังค์หรือช่องว่างหรือ "และ" (เช่น "สิบ" มีตัวอักษร 3 ตัว "สามสิบสี่" มี 10 ตัวอักษร "หนึ่งร้อยสี่สิบสาม" มี 20 ตัวอักษร)
  • ส่งกลับจำนวนตัวอักษรนั้น

สำหรับตัวเลขทั้งหมดที่ฉันเคยสนใจที่จะทดสอบสิ่งนี้จะมาบรรจบกันเป็น 4 เนื่องจาก "สี่" มีตัวอักษรสี่ตัวอยู่ด้วยจึงมีการวนซ้ำที่ไม่สิ้นสุดที่นี่ แทนที่จะเรียกว่าเวทมนตร์ตามแบบแผนเพื่อสิ้นสุดลำดับ

ความท้าทาย

ความท้าทายของคุณคือการสร้างโค้ดที่จะอ่านตัวเลขจากผู้ใช้จากนั้นพิมพ์บรรทัดที่แสดงฟังก์ชันการเปลี่ยนแปลงที่ถูกนำไปใช้ซ้ำ ๆ จนกว่า "four is magic" จะถึง

โดยเฉพาะ:

  1. แนวทางแก้ไขต้องเป็นโปรแกรมที่สมบูรณ์ในตัวเอง ไม่สามารถเป็นเพียงฟังก์ชันที่ใช้ตัวเลข - ปัจจัยในการป้อนข้อมูล
  2. ต้องอ่านอินพุตจากอินพุตมาตรฐาน (การต่อท่อจาก "echo" หรือการใช้การเปลี่ยนทิศทางอินพุตก็ใช้ได้เพราะมันมาจาก stdin ด้วย)
  3. ข้อมูลที่ป้อนควรอยู่ในรูปแบบตัวเลข
  4. สำหรับการประยุกต์ใช้ฟังก์ชันการแปลงทุกครั้งควรพิมพ์บรรทัด: a is b.โดยที่ a และ b เป็นรูปแบบตัวเลขของตัวเลขในการแปลง
  5. ต้องหยุดเต็ม (ช่วงเวลา)!
  6. 4 is magic.บรรทัดสุดท้ายเป็นธรรมชาติควรจะพูดว่า
  7. รหัสควรผลิตออกที่ถูกต้องสำหรับจำนวนทั้งหมดจาก0 ที่จะ 99

ตัวอย่าง:

> 4
4 is magic.

> 12
12 is 6.
6 is 3.
3 is 5.
5 is 4.
4 is magic.

> 42
42 is 8.
8 is 5.
5 is 4.
4 is magic.

> 0
0 is 4.
4 is magic.

> 99
99 is 10.
10 is 3.
3 is 5.
5 is 4.
4 is magic.

ผู้ชนะคือการส่งที่สั้นที่สุดโดยการนับอักขระซอร์สโค้ดซึ่งถูกต้องเช่นกัน

โบนัส

คุณอาจลองเขียนโค้ดเวอร์ชันที่พิมพ์ชื่อภาษาอังกฤษสำหรับตัวเลขด้วยแอปพลิเคชันของฟังก์ชันการแปลงแต่ละรายการ อินพุตต้นฉบับยังคงเป็นตัวเลข แต่บรรทัดเอาต์พุตควรมีรูปแบบคำของตัวเลข

(โบนัสสองเท่าสำหรับการวาดรูปทรงด้วยรหัสของคุณ)

(แก้ไข)คำชี้แจงบางประการ:

  1. ฉันต้องการให้คำนั้นปรากฏทั้งสองด้านในทุกกรณีเช่น Nine is four. Four is magic.
  2. ฉันไม่สนใจเรื่องการใช้อักษรตัวพิมพ์ใหญ่ และฉันไม่สนใจว่าคุณจะแยกคำว่าโทเค็นอย่างไรแม้ว่าพวกเขาควรแยกออกจากกัน: ninety-nineโอninety nineเคninetynineไม่เป็นไรไม่เป็นไร

ฉันกำลังพิจารณาหมวดหมู่เหล่านี้แยกต่างหากสำหรับการแข่งขันโบนัสโดยคำนึงถึงความท้าทายดังนั้นหากคุณต้องการสิ่งนี้อย่ากังวลว่ารหัสของคุณจะยาวกว่าเวอร์ชันตัวเลข

อย่าลังเลที่จะส่งหนึ่งโซลูชันสำหรับแต่ละเวอร์ชัน


1
เราควรจัดการกับตัวเลขที่สูงแค่ไหน? <100? <1,000? <1000000? <2 ** 31?
P Daddy

1
เนื่องจากสิ่งนี้ต้องไปจาก 0 ถึง 99 เท่านั้นฉันจึงสงสัยว่าวิธีแก้ปัญหาสั้น ๆ ที่รวดเร็วคือการฮาร์ดโค้ดค่าที่ 0-99 แมปไปแล้ววนซ้ำจนกว่าคุณจะถึง 4 หลังจากนั้นการสั่นแบบไมโครจะเริ่มขึ้น
Beska

@P Daddy ... ตอนที่ 6 บอกเพียง 0-99.
Beska

7
ดูสิ่งนี้ด้วย: stackoverflow.com/questions/309884/code-golf-number-to-words
ม็อบ

14
4 เป็นเพียงเวทมนตร์เพราะถูกเลือกโดยการทอยลูกเต๋าที่ยุติธรรม
VirtuosiMedia

คำตอบ:


57

GolfScript - 101 96 93 92 91 90 94 86 ไบต์

90 → 94: เอาต์พุตคงที่สำหรับการทวีคูณของ 10
94 → 86: รหัสที่ปรับโครงสร้างใหม่ ใช้ฐาน 100 เพื่อลบอักขระที่ไม่สามารถพิมพ์ได้
86 → 85: แคสต์สั้นลงเป็นสตริง

{n+~."+#,#6$DWOXB79Bd")base`1/10/~{~2${~1$+}%(;+~}%++=" is "\".
"1$4$4-}do;;;"magic."

ทำไมถึงตกต่ำขนาดนี้? มันสั้นกว่าเสียงกระเพื่อมและไม่ใช้ฟังก์ชันการจัดรูปแบบในตัว
Claudiu

36
ฉันชอบโค้ดที่ลงท้ายด้วย"magic."มันค่อนข้างสรุปได้
Aistina

@Aistina: เป็นเรื่องง่ายที่จะทำในความท้าทายนี้ฉันคิดว่า :-)
Platinum Azure

9
@Aistina: ฮ่าฮ่ามันตลกดี "mumbo jumbo yada yada..magic"
vol7ron

1
@P Daddy dสารสกัดจาก)as 100และใช้เป็นเลขฐานสำหรับการแปลงฐาน
Nabb

85

Perl ประมาณ 147 ถ่าน

ขึ้นอยู่กับโซลูชันของ Platinum Azure อย่างหลวม ๆ :

               chop
              ($_.=
              <>);@
             u="433
            5443554
           366  887
          798   866
         555    766
        "=~     /\d
       /gx      ;#4
      sub       r{4
     -$_        ?$_
    <20         ?$u
   [$_          ]:(
  $'?           $u[
 $']            :0)
+$u[18+$&]:magic}print"
$_ is ",$_=r(),'.'while
                /\d
                /x;
                444

1
@Platinum Azure วิธีที่ได้รับข้อมูลนี้คือผ่านการใช้งานpopโดยไม่มีข้อโต้แย้งใด ๆ ภายนอกรูทีนย่อยpopจะลบออกและส่งกลับค่าสุดท้าย@ARGVซึ่งเป็นรายการอาร์กิวเมนต์ของโปรแกรม Perl มันสามารถถูกแทนที่ได้อย่างง่ายดายshiftแต่เพิ่มอีก 2 ตัวอักษร ดู: p3rl.org/pop
Brad Gilbert

ดูเหมือนว่าคุณต้องมีอักขระขึ้นบรรทัดใหม่'.'ซึ่งเป็น 2 สำหรับ\nหรือ 1 หากคุณกำลังนับช่องว่างใน'. '(ช่องว่างที่เป็นตัวอักษรขึ้นบรรทัดใหม่)
vol7ron

หนังสือของฉันยาวกว่าเล็กน้อย แต่ความคิดสร้างสรรค์ไปได้ไกลในหนังสือของฉัน
Beska

@ Platinum Azure et al: เขาได้รับข้อมูลจาก stdin นั่นเป็นวิธีที่ต้องทำใน Perl (บางทีเขาอาจจะเปลี่ยนหลังจากความคิดเห็นของคุณ?)
แฟรงค์

@P Daddy: คร่ำครวญแต่ +1 ให้กับความคิดเห็นของคุณ
Platinum Azure

30

Common Lisp 157 Chars

เวอร์ชันใหม่ที่สอดคล้องกันมากขึ้นขณะนี้กำลังอ่านรูปแบบอินพุตมาตรฐานและละเว้นช่องว่างและขีดกลาง:

(labels((g (x)(if(= x 4)(princ"4 is magic.")(let((n(length(remove-if(lambda(x)(find x" -"))(format nil"~r"x)))))(format t"~a is ~a.~%"x n)(g n)))))(g(read)))

ในรูปแบบที่มนุษย์อ่านได้:

 (labels ((g (x)
           (if (= x 4)
            (princ "4 is magic.")
            (let ((n (length (remove-if (lambda(x) (find x " -"))
                                        (format nil "~r" x)))))
               (format t"~a is ~a.~%" x n)
               (g n)))))
    (g (read)))

และการทดสอบบางส่วน:

>24
24 is 10.
10 is 3.
3 is 5.
5 is 4.
4 is magic.

>23152436
23152436 is 64.
64 is 9.
9 is 4.
4 is magic.

และรุ่นโบนัส 165 ตัวอักษร:

 (labels((g(x)(if(= x 4)(princ"four is magic.")(let*((f(format nil"~r"x))(n(length(remove-if(lambda(x)(find x" -"))f))))(format t"~a is ~r.~%"f n)(g n)))))(g(read)))

การให้

>24
twenty-four is ten.
ten is three.
three is five.
five is four.
four is magic.

>234235
two hundred thirty-four thousand two hundred thirty-five is forty-eight.
forty-eight is ten.
ten is three.
three is five.
five is four.
four is magic.

5
ฉันคิดว่า "ยี่สิบสี่" มีเพียง 10 ตัวอักษร?
kennytm

1
ตัวเลขหลัง "is" ควรเป็นข้อความด้วย
Mike DeSimone

5
ทำไมถึงสูงขนาดนี้? คนอื่น ๆ ไม่ได้ใช้ฟังก์ชันรูปแบบในตัวและมีอักขระน้อยกว่า
Claudiu

3
@ Claudiu เพราะ Common Lisp นั้นยอดเยี่ยมมาก
Mornedhel

3
ไม่สำคัญว่าคุณจะเล่นกี่จังหวะถ้าคุณไม่ได้บอลในหลุม ผู้คนดูเหมือนจะลืมไปว่าเมื่อพวกเขาโหวตวิธีแก้ปัญหาที่ไม่ถูกต้อง
Mark Peters

21

Python 2.x, 144 150 154 166 ตัวอักษร

สิ่งนี้แยกจำนวนออกเป็นสิบและตัวและรวมเข้าด้วยกัน คุณสมบัติที่ไม่พึงปรารถนาของตัวดำเนินการ ternary หลอกa and b or cที่cส่งคืนหากbเป็น 0 จะถูกละเมิดที่นี่

n=input()
x=0x4d2d0f47815890bd2
while n-4:p=n<20and x/10**n%10or 44378/4**(n/10-2)%4+x/10**(n%10)%10+4;print n,"is %d."%p;n=p
print"4 is magic."

เวอร์ชันไร้เดียงสาก่อนหน้านี้ (150 ตัวอักษร) เพียงแค่เข้ารหัสความยาวทั้งหมดเป็นจำนวนเต็ม

n=input()
while n-4:p=3+int('1yrof7i9b1lsi207bozyzg2m7sclycst0zsczde5oks6zt8pedmnup5omwfx56b29',36)/10**n%10;print n,"is %d."%p;n=p
print"4 is magic."

ขอโทษค่ะฉันต้องการหยุดแบบเต็มเป็นพิเศษเพียงเพราะสิ่งนี้ :-) เข้าได้ดี! (แก้ไข: ฉันไม่รู้จัก Python แต่ทำได้n,"is",p,"."ไหมฉันคิดว่าคุณยังคงบันทึกอักขระบางตัวถ้าฉันนับถูก)
Platinum Azure

2
@ Plat: นั่นจะทำให้เกิดช่องว่างก่อนหน้าไฟล์..
kennytm

@Kenny ™: โอ้ดูฉันน่าจะสังเกตได้จากตัวอย่าง อ๊ะ! อย่างไรก็ตามอย่างที่บอกไปว่าข้อกำหนดบางอย่างได้รับการออกแบบมาโดยเฉพาะเพื่อให้ซับซ้อน :-)
Platinum Azure

เราสามารถย่อโดยใช้ฐานที่สูงกว่า 36 ได้หรือไม่?
MikeD

@MikeD: ไม่. จากเอกสาร Python: " พารามิเตอร์พื้นฐานให้ฐานสำหรับการแปลง (ซึ่งเป็น 10 โดยค่าเริ่มต้น) และอาจเป็นจำนวนเต็มในช่วง [2, 36] หรือศูนย์ก็ได้" ตอนนี้คุณอาจจะสามารถใช้ฟังก์ชั่นอื่น ๆ ที่ไม่ใช่int()พูดอะไรบางอย่างออกมาจากstructหรือbase64โมดูล ...
ไมค์ DeSimone

20

C - ด้วยจำนวนคำ

445 431 427 421 399 386 371 359 * 356 354 348 347 ตัวอักษร

แค่นั้นแหละ. ฉันไม่คิดว่าจะทำให้สั้นลงได้ขนาดนี้

การขึ้นบรรทัดใหม่ทั้งหมดมีไว้เพื่อให้อ่านง่ายและสามารถลบออกได้:

ด้านล่างนี้มีความเป็นเอกภาพอยู่บ้าง แต่ก็ยังอ่านยาก ดูด้านล่างสำหรับเวอร์ชันที่อ่านได้มากขึ้น

ขยายความและแสดงความคิดเห็น:

เกี่ยวกับสตริงที่เข้ารหัสใกล้จุดเริ่มต้น

ชื่อของตัวเลขจะถูกบีบอัดโดยใช้รูปแบบที่เรียบง่ายมาก สตริงย่อยที่ใช้บ่อยจะถูกแทนที่ด้วยดัชนีหนึ่งอักขระในอาร์เรย์ชื่อ "ตารางการค้นหา" ของรายการชื่อพิเศษจะถูกเพิ่มไว้ที่ส่วนท้ายสำหรับสตริงย่อยที่ไม่ได้ใช้อย่างครบถ้วนในชุดแรก การค้นหาเป็นแบบวนซ้ำ: รายการสามารถอ้างถึงรายการอื่น ๆ

ยกตัวอย่างเช่นชื่ออัด elM11 print()ฟังก์ชั่นเอาท์พุทตัวละครeและl(กรณีที่ต่ำกว่า 'L' ไม่ใช่จำนวน '1') คำต่อคำ แต่แล้วก็พบMจึงเรียกตัวเองมีค่าดัชนีของรายการที่ 29 (ASCII 'M' - ASCII '0') ลงในตารางการค้นหา สตริงนี้evLจึงเป็นเอาต์พุตeและvเรียกตัวเองอีกครั้งด้วยดัชนีของรายการที่ 28 ในตารางการค้นหาซึ่งก็คือenและเป็นเอาต์พุตคำต่อคำ สิ่งนี้มีประโยชน์เนื่องจากenยังใช้ในeLสำหรับeen(ใช้eightในภายหลังeighteen) ซึ่งใช้tOสำหรับteen(ใช้สำหรับ-teenชื่ออื่น ๆ)

โครงร่างนี้ส่งผลให้เกิดการบีบอัดชื่อตัวเลขที่ค่อนข้างสำคัญในขณะที่ต้องการโค้ดเพียงเล็กน้อยในการคลายการบีบอัด

เครื่องหมายจุลภาคที่จุดเริ่มต้นและจุดสิ้นสุดของบัญชีสตริงสำหรับวิธีง่ายๆที่พบสตริงย่อยภายในสตริงนี้ การเพิ่มอักขระสองตัวที่นี่จะช่วยประหยัดอักขระเพิ่มเติมในภายหลัง

เกี่ยวกับการละเมิดของ main()

argvถูกละเว้น (ดังนั้นจึงไม่ได้ประกาศในเวอร์ชันบีบอัด) ค่าของ argc จะถูกละเว้น แต่หน่วยเก็บข้อมูลจะถูกใช้ซ้ำเพื่อเก็บหมายเลขปัจจุบัน นี่ช่วยให้ฉันไม่ต้องประกาศตัวแปรพิเศษ

เกี่ยวกับการขาด #include

บางคนจะบ่นว่าการละเว้น#include <stdio.h>เป็นการโกง มันไม่ได้เลย ให้เป็นโปรแกรม C ที่ถูกต้องตามกฎหมายซึ่งจะรวบรวมอย่างถูกต้องบนคอมไพเลอร์ C ใด ๆ ที่ฉันรู้จัก (แม้ว่าจะมีคำเตือน) หากขาด Protoypes สำหรับฟังก์ชัน stdio คอมไพเลอร์จะถือว่าเป็นฟังก์ชัน cdecl ที่ส่งคืนintและจะเชื่อมั่นว่าคุณรู้ว่าจะส่งอาร์กิวเมนต์ใด ค่าที่ส่งคืนจะถูกละเว้นในโปรแกรมนี้และเป็นฟังก์ชันทั้งหมดของ cdecl ("C" Calling convention) และเรารู้ว่าจะส่งผ่านข้อโต้แย้งใด

เอาต์พุต

ผลลัพธ์เป็นไปตามที่คาดไว้:

0
ศูนย์คือสี่
สี่คือเวทมนตร์
1
หนึ่งคือสาม
สามคือห้า
ห้าคือสี่
สี่คือเวทมนตร์
4
สี่คือเวทมนตร์
20
ยี่สิบคือหก
หกคือสาม
สามคือห้า
ห้าคือสี่
สี่คือเวทมนตร์
21
ยี่สิบเอ็ดคือเก้า
เก้าคือสี่
สี่คือเวทมนตร์

*เวอร์ชันก่อนหน้าพลาดเครื่องหมายในสองส่วนของข้อมูลจำเพาะ: ไม่ได้จัดการกับศูนย์และรับอินพุตในบรรทัดคำสั่งแทน stdin การจัดการกับเลขศูนย์ที่เพิ่มอักขระ แต่ใช้ stdin แทน args บรรทัดคำสั่งเช่นเดียวกับการเพิ่มประสิทธิภาพอื่น ๆ อีกสองสามตัวบันทึกจำนวนอักขระเท่ากันส่งผลให้มีการล้าง

ข้อกำหนดมีการเปลี่ยนแปลงเพื่อให้ชัดเจนว่าควรพิมพ์คำตัวเลขทั้งสองด้านของ "คือ" เวอร์ชันใหม่นี้เป็นไปตามข้อกำหนดนั้นและดำเนินการเพิ่มประสิทธิภาพอีกสองสามครั้งเพื่อ (มากกว่า) บัญชีสำหรับขนาดพิเศษที่จำเป็น


นี่เป็นคำตอบที่ฉันชอบอย่างง่ายดาย ... ไชโยทำได้ดีมาก +1 สำหรับคุณและถ้าฉันสามารถให้สองเครื่องหมายถูกฉันจะทำ
Platinum Azure

5
อ่านสนุกดีฉันคิดว่าฉันจะใช้ตัวเลขเหล่านี้ในชีวิตประจำวัน หก, เซม, แปด, เก้า, เทล, เอเลม, สิบสอง, เอนปี, โฟร์ปี, ฟิฟฟี่, หกปี, เซเว่นพี, แปดโฮ, ไนน์พี, ทเวลคิว ... =)
เดค

10

J, 107 112ตัวอักษร

'4 is magic.',~}:('.',~":@{.,' is ',":@{:)"1]2&{.\.
(]{&(#.100 4$,#:3 u:ucp'䌵䐵吶梇禈榛ꪛ멩鮪鮺墊馊꥘誙誩墊馊ꥺ겻곋榛ꪛ멩鮪鮺'))^:a:

(ขึ้นบรรทัดใหม่เพื่อการอ่านเท่านั้น)

การใช้งานและผลลัพธ์:

    '4 is magic.',~}:('.',~":@{.,' is ',":@{:)"1]2&{.\.(]{&(#.100 4$,#:3 u:ucp'䌵䐵吶梇禈榛ꪛ멩鮪鮺墊馊꥘誙誩墊馊ꥺ겻곋榛ꪛ멩鮪鮺'))^:a:12
12 is 6.    
6 is 3.     
3 is 5.     
5 is 4.     
4 is magic. 

บิต "4 is magic" อยู่ที่ไหน แล้ว "อยู่" ตรงกลางล่ะ?
Josh K

3
โปรดเลือกผู้ตัดสินที่ไม่ใช่คนจีน
ดร. belisarius

3
@beli: 멩, 겻, 곋, 멩เป็นคนเกาหลี
kennytm

1
ภรรยาของฉัน (เจ้าของภาษาจีน) บอกว่าเป็นการผสมผสานระหว่างภาษาจีนและภาษาเกาหลี
Loren Pechtel

3
@belisarius: 1) เธอไม่รู้ภาษาเกาหลี 2) คนจีนพูดพล่อยๆ
Loren Pechtel

10

T-SQL, 413451 499ตัวอักษร

CREATE FUNCTION d(@N int) RETURNS int AS BEGIN
Declare @l char(50), @s char(50)
Select @l='0066555766',@s='03354435543668877987'
if @N<20 return 0+substring(@s,@N+1,1) return 0+substring(@l,(@N/10)+1,1) + 0+(substring(@s,@N%10+1,1))END
GO
CREATE proc M(@x int) as BEGIN
WITH r(p,n)AS(SELECT p=@x,n=dbo.d(@x) UNION ALL SELECT p=n,n=dbo.d(n) FROM r where n<>4)Select p,'is',n,'.' from r print '4 is magic.'END

(ไม่ใช่ว่าฉันแนะนำอย่างจริงจังให้คุณทำสิ่งนี้ ... จริงๆฉันแค่อยากจะเขียน CTE)

ใช้:

M 95

ผลตอบแทน

p                n
----------- ---- -----------
95          is   10.
10          is   3.
3           is   5.
5           is   4.
4 is magic.

คุณไม่สามารถพิมพ์ผลการค้นหาแต่ละรายการแทนที่จะส่งคืนตารางได้หรือไม่? นั่นจะทำให้ผลลัพธ์ดูดีขึ้น
โจอี้

1
ฉันไม่คิดว่ามันจัดการกับศูนย์ได้อย่างเหมาะสม เกี่ยวกับสิ่งนี้:CREATE FUNCTION d(@ int) RETURNS int AS BEGIN Declare @l char(9),@s char(50) Select @l='066555766',@s='03354435543668877987' if @=0 return 4 if @<20 return 0+substring(@s,@+1,1)return 0+substring(@l,@/10,1)+substring(@s,@%10+1,1)END
Gabe

9

Java (พร้อมแผ่นสำเร็จรูป) 308 290 286 282 280 อักขระ

class A{public static void main(String[]a){int i=4,j=0;for(;;)System.out.printf("%d is %s.%n",i=i==4?new java.util.Scanner(System.in).nextInt():j,i!=4?j="43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:".charAt(i)-48:"magic");}}

ฉันแน่ใจว่า Groovy จะกำจัดสิ่งนั้นได้มาก

คำอธิบายและการจัดรูปแบบ (ความคิดเห็นทั้งหมดขึ้นบรรทัดใหม่และช่องว่างนำหน้า / ต่อท้ายถูกลบออกในจำนวน):

ตรงไปตรงมาพอสมควร แต่

//boilerplate
class A{
   public static void main(String[]a){
      //i is current/left number, j right/next number.  i=4 signals to start
      //by reading input
      int i=4,j=0;
      for(;;)
         //print in the form "<left> is <right>."
         System.out.printf(
            "%d is %s.%n",
            i=i==4?
               //<left>: if i is 4 <left> will be a new starting number
               new java.util.Scanner(System.in).nextInt():
               //otherwise it's the next val
               j,
            i!=4?
               //use string to map number to its length (:;< come after 9 in ASCII)
               //48 is value of '0'.  store in j for next iteration
               j="43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:".charAt(i)-48:
               //i==4 is special case for right; print "magic"
               "magic");
   }
}

แก้ไข: ไม่ใช้ฐานสิบหกอีกต่อไปนี่เป็นการกดแป้นพิมพ์น้อยลง


1
249 โดยไม่ต้องนำเข้า class def หรือ main def
Mark Peters

1
นั่นคือปีศาจ ฉันชอบฐาน 16 (+1)
Platinum Azure

คุณสามารถประหยัดพื้นที่ได้หนึ่งช่องโดยใช้String[]aแทนString[] aไฟล์.
BalusC

ขอบคุณ @Balus กำจัดพวงด้วยการคำนวณเลขคณิตง่ายๆกับอักขระแทนที่จะใช้การแยกวิเคราะห์เลขฐานสิบหก
Mark Peters

@ มาร์คปีเตอร์ส: น่ารังเกียจกว่า ฉันรู้สึกวานิลลาเมื่อเทียบกับสิ่งนั้น
Platinum Azure

9

Windows PowerShell: 152 153 184ไบต์

ตามโซลูชันก่อนหน้าซึ่งมีอิทธิพลมากขึ้นจากโซลูชันอื่น ๆ

$o="03354435543668877988"
for($input|sv b;($a=$b)-4){if(!($b=$o[$a])){$b=$o[$a%10]-48+"66555766"[($a-$a%10)/10-2]}$b-=48-4*!$a
"$a is $b."}'4 is magic.'

แก้ไขเพื่อรองรับการทวีคูณของ 10 ("เก้าสิบ" แทนที่จะเป็น "เก้าสิบศูนย์")
Gabe

เฮ้ @Gabe :) ขอบคุณ; ช่วงนี้ไม่ค่อยมีเวลาตีกอล์ฟ ยังคงคำพูดรอบ$inputต้องอยู่ตั้งแต่คุณไม่สามารถโยนแจงนับโดยตรงกับint; ใช้งานได้เมื่อผ่านstringครั้งแรก :-)
Joey

8

C, 158 อักขระ

main(n,c){char*d="03354435543668877988";for(scanf("%d",&n);n-4;n=c)printf("%d is %d.\n",n,c=n?n<19?d[n]-48:d[n%10]-"_,**+++)**"[n/10]:4);puts("4 is magic.");}

(เดิมใช้รหัส Python ของ Vlad ยืมเคล็ดลับจากโซลูชัน C ++ ของ Tom Sirgedas เพื่อบีบอักขระเพิ่มอีกสองสามตัว)

เวอร์ชันขยาย:

main(n, c) {
    char *d = "03354435543668877988";
    for (scanf("%d",&n); n-4; n = c)
        printf("%d is %d.\n", n, c = n ? n<19 ? d[n]-48 : d[n%10] - "_,**+++)**"[n/10]  : 4);
    puts("4 is magic.");
}

ดูเหมือนจะไม่ได้ผลสำหรับฉัน: ./magic 10 10 คือ -27 ความผิดในการแบ่งส่วน
Casey

@ Casey - การโทร scanf () เป็นภาพร่างเล็กน้อย กำลังอ่าน int เป็นตัวอักษร ฉันกำลังหนีไปกับมันบน OSX และบน Windows มันใช้งานได้ แต่ล้มเหลวเมื่อออก ดังนั้นฉันจึงสร้าง n & c ints อีกครั้ง ฉันรู้ว่าฉันสามารถวางคำหลัก int ได้โดยสร้างพารามิเตอร์โดยใช้สัญลักษณ์ K&R ผลลัพธ์จะปลอดภัยกว่าและสั้นกว่าหนึ่งอักขระ
Ferruccio

คุณสามารถบันทึกอักขระได้ 3 ตัวโดยแทนที่ " 466555766" [n / 10] + d [n% 10] -96 ด้วย d [n% 10] - " , +++) " [n / 10]
Tom Sirgedas

6

งูหลาม 129 133 137 148 ตัวอักษร

ในการอุ่นเครื่องนี่เป็นเวอร์ชันแรกของฉัน (ปรับปรุงตัวอักษรสองสามตัวเหนือ Python ที่ดีที่สุดก่อนหน้านี้)

ปล. หลังจากการทำซ้ำสองสามครั้งตอนนี้สั้นลงประมาณยี่สิบตัว:

n=input()
while n-4:p=(922148248>>n/10*3&7)+(632179416>>n%10*3&7)+(737280>>n&1)+4*(n<1);print n,'is %d.'%p;n=p
print'4 is magic.'

6

C #: 210 ตัวอักษร

Squished:

using C=System.Console;class B{static void Main(){int
x=0,y=int.Parse(C.ReadLine());while(x!=4)C.Write((x=y)+" is {0}.\n",x==4?"magic":""+(y=x==0?4:"03354435543668877988"[x<20?x:x%10]+"0066555766"[x/10]-96));}}

ขยาย:

using C=System.Console;
class B
{
    static void Main()
    {
        int x=0,y=int.Parse(C.ReadLine());
        while(x!=4)
            C.Write((x=y)+" is {0}.\n",
                x==4?
                     "magic":
                     ""+(y= x==0?
                                4:
                                "03354435543668877988"[x<20?x:x%10]+
                                "0066555766"[x/10]-96)
                   );
    }
}

เคล็ดลับวิธีนี้ใช้:

  • สร้างตารางการค้นหาสำหรับความยาวของชื่อตัวเลขตามตัวเลขที่ปรากฏในตัวเลข
  • ใช้การค้นหาอาร์เรย์อักขระบนสตริงและการคำนวณทางคณิตศาสตร์แทนอาร์เรย์ตัวเลข
  • ใช้นามแฝงชื่อคลาสเพื่อย่อConsole.เป็นC.
  • ใช้เงื่อนไข (ternary) ผู้ประกอบการ ( ?:) if/elseแทน
  • ใช้\nกับWriteรหัสการหลบหนีแทนWriteLine
  • ใช้ข้อเท็จจริงที่ว่า C # มีลำดับการประเมินที่กำหนดไว้เพื่ออนุญาตการมอบหมายภายในการWriteเรียกใช้ฟังก์ชัน
  • ใช้นิพจน์การกำหนดเพื่อกำจัดข้อความเพิ่มเติมและเครื่องหมายวงเล็บเสริม

int[] zจะสั้นลงเนื่องจากไม่ต้องการnew[]
Joey

แก้ไขให้ใช้การคำนวณอักขระแทนการค้นหาอาร์เรย์
LBushkin

@ mdm20: คุณพูดถูก ฉันมีข้อผิดพลาดในตารางการค้นหา แก้ไขแล้ว
LBushkin

ครั้งที่สิบสองคือเสน่ห์: * D
LBushkin

quicky เพื่อประหยัด 5 ตัวอักษร: สั้นกว่าหล่อ"magic"เพื่อobjectจะเป็นไปโดยปริยายเรียกToString()บนโดยการเพิ่มy ""แต่เพราะ+มีความสำคัญสูงกว่า?:คุณจะต้องใส่ไว้ในความจริงส่วนหนึ่งแทนการเท็จx!=4?y+"":"magic"ส่วนหนึ่ง:
P Daddy

6

Perl: 148 อักขระ

(Perl: 233 181 212 206 200 199 198 185 179 149 148 ตัวอักษร)

  • ย้ายข้อยกเว้นแฮชไปยังอาร์เรย์หน่วย สิ่งนี้ส่งผลให้ฉันสามารถตัดตัวละครได้มาก :-)
  • mobrule ชี้ให้เห็นข้อบกพร่องที่น่ารังเกียจ แก้ไขด่วนเพิ่ม 31 ตัวอุ๊ย!
  • ปรับโครงสร้างใหม่สำหรับกรณีพิเศษเป็นศูนย์การเล่นกอล์ฟแบบไม่รุนแรงทำได้เช่นกัน
  • เข้าถึงรายการโดยตรงสำหรับการใช้งานครั้งเดียวแทนที่จะจัดเก็บในอาร์เรย์? ใช่!
  • การตอบสนองที่มากสำหรับตัวละครเลือดเพียงตัวเดียว นี่คือชีวิตของนักกอล์ฟอย่างแท้จริง :-(
  • อ๊ะแก้ไขช่องว่างง่ายๆ 198 ตอนนี้.
  • เปลี่ยนรหัสซ้ำซ้อนบางส่วน
  • คำหลักที่ส่งคืนสุดท้ายในrนั้นไม่จำเป็นต้องโกนออกไปอีก
  • การปรับโครงสร้างจำนวนมากต่อความคิดเห็น น่าเสียดายที่ฉันทำได้แค่ 149 เพราะฉันต้องแก้ไขข้อบกพร่องที่มีอยู่ทั้งในโค้ดก่อนหน้าและเวอร์ชันของผู้แสดงความคิดเห็น
  • ลองใช้ "เวทมนตร์"

ให้ลูกบอลกลิ้งด้วยความพยายามเล็กน้อยใน Perl

@u=split'','4335443554366887798866555766';$_=<>;chop;print"$_ is ".($_=$_==4?0:$_<20?$u[$_]:($u[$_/10+18]+($_%10&&$u[$_%10]))or magic).".
"while$_

เคล็ดลับ:

มากเกินไป!


อ๊าก! ฉันไม่เคยทดสอบอย่างไรว่าฉันจะไม่มีวันรู้
Platinum Azure

คุณมีรหัสตายอยู่ในนั้นหรือไม่? ฉันไม่เห็นว่ากรณีพิเศษสำหรับศูนย์มีความจำเป็นอย่างไรเมื่อ $ u [0] เป็น 4 ฉันมีโค้ด @ 166 ตัวอักษรเวอร์ชันที่ใช้งานได้จริงและฉันคิดว่ามันมีพื้นที่ให้สั้นกว่านั้นเล็กน้อย
ฮอบส์

@hobbs: จุดดีฉันจะดูอีกครั้ง เรื่องคือฉันได้ครึ่งทางจากการแก้ไขสองสามครั้งและทันใดนั้นสิ่งต่างๆก็พัง (ณ จุดที่ฉันเลือกให้มี 4 -> 0) ฉันคิดว่าคุณมาถูกที่แล้วแม้ว่า :-)
Platinum Azure

ฉันไม่คิดว่าตัวเองเป็นโปรแกรมเมอร์ Perl ที่ยอดเยี่ยม แต่คุณสามารถลดอักขระบางตัวได้: @u=split$x,'43350435543668877988';เครื่องหมายจุลภาคของคุณใช้อักขระ 19 ตัวที่ไม่จำเป็นโดยแยกเป็นundefส่วน ๆ ในทุกๆอักขระฉันใช้$xเป็นตัวแปรที่ไม่ได้กำหนดเพื่อแทนที่ "undef` - ทั้งหมด เงินออม: 11 ตัวอักษร นอกจากนี้ให้ลบmอินchompและคุณจะได้รับตัวละครอื่นที่ถูกตัดคะแนนของคุณ
vol7ron

ทำได้ดีกว่า แต่คุณยังสามารถประหยัดได้มากขึ้นด้วยการสูญเสียsub rทั้งหมด - คุณใช้เพียงครั้งเดียวและคุณสามารถแทนที่ทั้งหมดได้ด้วยเทอร์นารีที่ซ้อนกันเพียงตัวเดียว เวอร์ชันของฉันคือ 144 ตัวอักษรในตอนนี้: gist.github.com/473289
hobbs

5

JavaScript 1.8 (SpiderMonkey) - 153 ตัวอักษร

l='4335443554366887798866555766'.split('')
for(b=readline();(a=+b)-4;print(a,'is '+b+'.'))b=a<20?l[a]:+l[18+a/10|0]+(a%10&&+l[a%10])
print('4 is magic.')

การใช้งาน: echo 42 | js golf.js

เอาท์พุต:

42 is 8.
8 is 5.
5 is 4.
4 is magic.

พร้อมโบนัส - 364 ตัวอักษร

l='zero one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty thirty fourty fifty sixty seventy eighty ninety'.split(' ')
z=function(a)a<20?l[a]:l[18+a/10|0]+(a%10?' '+l[a%10]:'')
for(b=+readline();(a=b)-4;print(z(a),'is '+z(b)+'.'))b=z(a).replace(' ','').length
print('four is magic.')

เอาท์พุต:

เก้าสิบเก้าคือสิบ
สิบคือสาม
สามคือห้า
ห้าคือสี่
สี่คือเวทมนตร์

4

Haskell 224 270อักขระ

o="43354435543668877988"
x!i=read[x!!i]
n x|x<20=o!x|0<1="0066555766"!div x 10+o!mod x 10
f x=zipWith(\a b->a++" is "++b++".")l(tail l)where l=map show(takeWhile(/=4)$iterate n x)++["4","magic"]
main=readLn>>=mapM putStrLn.f

และอ่านได้มากขึ้น -

ones = [4,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,8,8]
tens = [0,0,6,6,5,5,5,7,6,6]

n x = if x < 20 then ones !! x else (tens !! div x 10) + (ones !! mod x 10)

f x = zipWith (\a b -> a ++ " is " ++ b ++ ".") l (tail l)
    where l = map show (takeWhile (/=4) (iterate n x)) ++ ["4", "magic"]
    
main = readLn >>= mapM putStrLn . f

4

เวอร์ชัน C ++ Stdio ย่อขนาด: 196 อักขระ

#include <cstdio>
#define P;printf(
char*o="43354435543668877988";main(int p){scanf("%d",&p)P"%d",p);while(p!=4){p=p<20?o[p]-48:"0366555966"[p/10]-96+o[p%10]P" is %d.\n%d",p,p);}P" is magic.\n");}

เวอร์ชัน C ++ Iostreams ย่อขนาด: 195 อักขระ

#include <iostream>
#define O;std::cout<<
char*o="43354435543668877988";main(int p){std::cin>>p;O p;while(p!=4){p=p<20?o[p]-48:"0366555966"[p/10]-96+o[p%10]O" is "<<p<<".\n"<<p;}O" is magic.\n";}

ต้นฉบับไม่ได้ลดขนาด: 344 อักขระ

#include <cstdio>

int ones[] = { 4, 3, 3, 5, 4, 4, 3, 5, 5, 4, 3, 6, 6, 8, 8, 7, 7, 9, 8, 8 };
int tens[] = { 0, 3, 6, 6, 5, 5, 5, 9, 6, 6 };

int n(int n) {
    return n<20 ? ones[n] : tens[n/10] + ones[n%10];
}

int main(int p) {
    scanf("%d", &p);
    while(p!=4) {
        int q = n(p);
        printf("%i is %i\n", p, q);
        p = q;
    }
    printf("%i is magic\n", p);
}

แก้ไขแล้ว. มันทำให้สั้นลงเล็กน้อยด้วย
Mike DeSimone

ทำได้ดีมาก (ฉันหัวเราะมากกับปริศนา std 20 ตัว!)
Platinum Azure

ใช่นั่นเป็น headbanger ที่แท้จริงจนกว่าฉัน#defineจะเริ่มต้นว่ามันจะสั้นกว่านี้อีกเพราะมันสามารถแทนที่โทเค็นได้หลายอัน
Mike DeSimone

printf("is magic".\n)=> puts. printf("%d",p)=> puts(atoi(p)). ไม่เพียง แต่สั้นลง แต่เร็วขึ้นด้วย
Ben Voigt

2
@ Mike DeSimone: ฉันคิดว่าwhile(p!=4)อาจจะสั้นลงเป็นwhile(p-4). ตัวละครตัวเดียวฉันรู้ แต่ก็ยัง :-)
Platinum Azure

3

Delphi: 329 อักขระ

เวอร์ชันบรรทัดเดียว:

program P;{$APPTYPE CONSOLE}uses SysUtils;const S=65;A='EDDFEEDFFEDGGIIHHJII';B='DGGFFFJGG';function Z(X:Byte):Byte;begin if X<20 then Z:=Ord(A[X+1])-S else Z:=(Ord(B[X DIV 10])-S)+Z(X MOD 10)end;var X,Y:Byte;begin Write('> ');ReadLn(X);repeat Y:=Z(X);WriteLn(Format('%d is %d.',[X,Y]));X:=Y;until X=4;WriteLn('4 is magic.');end.

รูปแบบ:

program P;

{$APPTYPE CONSOLE}

uses
  SysUtils;

const
  S = 65;
  A = 'EDDFEEDFFEDGGIIHHJII';
  B = 'DGGFFFJGG';

function Z(X:Byte):Byte;
begin
  if X<20
  then Z := Ord(A[X+1])-S
  else Z := (Ord(B[X DIV 10])-S) + Z(X MOD 10);
end;

var
  X,Y: Byte;

begin
  Write('> ');
  ReadLn(X);

  repeat
    Y:=Z(X);
    WriteLn(Format('%d is %d.' , [X,Y]));
    X:=Y;
  until X=4;

  WriteLn('4 is magic.');
end.

อาจมีที่ว่างสำหรับการบีบมากขึ้น ... :-P


3

C # 314 286 283 274 289 273252ตัวอักษร

Squished:

252 

ปกติ:

using C = System.Console;
class P
{
    static void Main()
    {
        var x = "4335443554366877798866555766";
        int m, o, v = int.Parse(C.ReadLine());
        do {
            C.Write("{0} is {1}.\n", o = v, v == 4 ? (object)"magic" : v = v < 20 ? x[v] - 48 : x[17 + v / 10] - 96 + ((m = v % 10) > 0 ? x[m] : 48));
        } while (o != 4);
        C.ReadLine();
    }
}

แก้ไข Dykam: การแทรกและการเปลี่ยนแปลงค่อนข้างระมัดระวัง:

  • เปลี่ยน l ToString () เป็นการร่ายเป็นobjectของstring "magic".
  • สร้างตัวแปรชั่วคราวoดังนั้นฉันจึงสามารถย้ายbreakนอกforลูปได้นั่นคือทำให้เกิดไฟล์do-while.
  • inlined oมอบหมายเช่นกันvมอบหมาย continueing ในการแทรกการคำนวณในการขัดแย้งการทำงานโดยสิ้นเชิงลบความจำเป็นในการl lนอกจากนี้ยังได้รับมอบหมาย inlined mของ
  • ลบออกพื้นที่ในint[] x, int[]xคือ Legit เกินไป
  • พยายามที่จะแปลงอาร์เรย์เป็นการแปลงสตริง แต่using System.Linqมันมากเกินไปที่จะทำการปรับปรุงนี้

แก้ไข 2 Dykam เปลี่ยน int array เป็น char array / string เพิ่ม arithmics ที่เหมาะสมเพื่อแก้ไขสิ่งนี้


ใช่แล้วมันสั้นกว่าเวอร์ชัน Java
Dykam

3

Lua 176 ตัวอักษร

o={[0]=4,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,8,8}t={3,6,6,5,5,5,7,6,6}n=0+io.read()while n~=4 do a=o[n]or o[n%10]+t[(n-n%10)/10]print(n.." is "..a..".")n=a end print"4 is magic."

หรือ

  o={[0]=4,3,3,5,4,4
  ,3,5,5,4,3,6,6,8,8
  ,7,7,9,8,8}t={3,6,
   6,5,5,5,7,6,6}n=
   0+io.read()while
   n ~= 4 do a= o[n
   ]or o[n%10]+t[(n
   -n%10)/10]print(
n.." is "..a.."." )n=a
end print"4 is magic."

3

C - ไม่มีคำจำนวน

180 175 * 172 167 ตัวอักษร

การขึ้นบรรทัดใหม่ทั้งหมดมีไว้เพื่อให้อ่านง่ายและสามารถลบออกได้:

unminified เล็กน้อย:

*เวอร์ชันก่อนหน้าพลาดเครื่องหมายในสองส่วนของข้อมูลจำเพาะ: ไม่ได้จัดการกับศูนย์และรับอินพุตในบรรทัดคำสั่งแทน stdin การจัดการอักขระที่เพิ่มเป็นศูนย์ แต่ใช้ stdin แทน args บรรทัดคำสั่งจะช่วยประหยัดได้มากขึ้นส่งผลให้ประหยัดเน็ต


2

perl, 123 122 ตัวอักษร

เพิ่งตระหนักว่าไม่มีข้อกำหนดในการส่งออกไปยัง STDOUT ดังนั้นให้ส่งออกไปยัง STDERR แทนและเคาะอักขระอื่นออก

@u='0335443554366887798866555766'=~/./g;$_+=<>;warn"$_ is ",$_=$_-4?$_<20?$u[$_]||4:$u[chop]+$u[$_+18]:magic,".\n"until/g/

และเวอร์ชันที่ส่งกลับการสะกดตัวเลข:

279 278 276 280 อักขระ

@p=(Thir,Four,Fif,Six,Seven,Eigh,Nine);@n=("",One,Two,Three,Four,Five,@p[3..6],Ten,Eleven,Twelve,map$_.teen,@p);s/u//for@m=map$_.ty,Twen,@p;$n[8].=t;sub n{$n=shift;$n?$n<20?$n[$n]:"$m[$n/10-2] $n[$n%10]":Zero}$p+=<>;warnt$m=n($p)," is ",$_=$p-4?n$p=()=$m=~/\w/g:magic,".\n"until/c/

แม้ว่าจะเป็นไปตามข้อกำหนด แต่ก็ไม่ได้มีรูปแบบที่ดี 100% ส่งคืนช่องว่างเพิ่มเติมหลังจากตัวเลขที่ลงท้ายด้วยศูนย์ ข้อมูลจำเพาะกล่าวว่า:

"ฉันไม่สนใจว่าคุณจะแยกคำว่าโทเค็นอย่างไรแม้ว่าพวกเขาควรแยก"

นั่นเป็นสิ่งที่อ่อนแอ รุ่นที่ถูกต้องมากขึ้นที่

282 281 279 283 อักขระ

@p=(Thir,Four,Fif,Six,Seven,Eigh,Nine);@n=("\x8",One,Two,Three,Four,Five,@p[3..6],Ten,Eleven,Twelve,map$_.teen,@p);s/u//for@m=map$_.ty,Twen,@p;$n[8].=t;sub n{$n=shift;$n?$n<20?$n[$n]:"$m[$n/10-2]-$n[$n%10]":Zero}$p+=<>;warn$m=n($p)," is ",$_=$p-4?n$p=()=$m=~/\w/g:magic,".\n"until/c/

1

Python:

#!/usr/bin/env python

# Number of letters in each part, we don't count spaces
Decades = ( 0, 3, 6, 6, 6, 5, 5, 7, 6, 6, 0 )
Smalls  = ( 0, 3, 3, 5, 4, 4, 3, 5, 5, 4 )
Teens  =  ( 6, 6, 8, 8, 7, 7, 9, 8, 8 )

def Count(n):
    if n > 10 and n < 20: return Teens[n-11]
    return   Smalls[n % 10 ] + Decades [ n / 10 ]

N = input()

while N-4:
    Cnt = Count(N)
    print "%d is %d" % ( N, Cnt)
    N = Cnt

print "4 is magic"

4
ฉันชอบมัน. คุณอาจจะกระชับขึ้นอีกนิดก็ได้
Josh K

@ วลาด: ควรอ่านอินพุตจาก stdin แทนจากอาร์กิวเมนต์ นั่นหมายความว่าคุณสามารถใช้N = input()(หรือraw_input()) และกำจัดsysสิ่งต่างๆได้
kennytm

นอกจากนี้คุณสามารถสร้าง Smalls ได้รวมถึงวัยรุ่นด้วยคำสั่ง if จะเป็น "if n <20: return Smalls [n]" เท่านั้น Smalls จะยังคงใช้งานได้สำหรับกรณี> = 20 เนื่องจากโมดูลัส 10
Jon Smock

5
นี่ต้องเป็นครั้งแรกที่ฉันเห็น (ตัวเลือกเต็ม) she-bangในคำตอบรหัสกอล์ฟ ;-)
ChristopheD

ดูเหมือนจะเป็นการเริ่มต้นที่ดี ... กระชับขึ้นอย่างแน่นอนแม้แต่ Python ก็ไม่ต้องการช่องว่างทั้งหมดนี้ :-) นอกจากนี้ตามที่ Ferruccio ชี้ให้เห็นว่า 0 ไม่ทำงานโดยเฉพาะดูเหมือนว่าจะวนซ้ำไม่สิ้นสุด
Platinum Azure

1

C ++, 171 อักขระ (#include ละไว้)

void main(){char x,y,*a="03354435543668877988";scanf("%d",&x);for(;x-4;x=y)y=x?x<19?a[x]-48:"_466555766"[x/10]+a[x%10]-96:4,printf("%d is %d.\n",x,y);puts("4 is magic.");}

ฉันคิดว่าถ้าคุณคิดว่านี่เป็น C คุณสามารถหลีกเลี่ยงความจำเป็นในการใช้งานได้#includeเนื่องจากฟังก์ชันจะถือว่าใช้intพารามิเตอร์ คุณยังสามารถบันทึกจังหวะโดยการทำผลตอบแทนmain int
Gabe

1

ทับทิม 164 ตัวอักษร

n=gets.to_i;s="03354435543668877987";if n==0;puts"0 is 4.";else;puts"#{n} is #{n=(n<20)?s[n]-48:"0066555766"[n/10]-48+s[n%10]-48}." until n==4;end;puts"4 is magic."

ถอดรหัส:

n = gets.to_i
s = "03354435543668877987"
if n == 0
  puts "0 is 4."
else
  puts "#{n} is #{n = (n < 20) ? s[n] - 48 : "0066555766"[n / 10] - 48 + s[n % 10] - 48}." until n == 4
end

puts "4 is magic."

วิธีแก้ปัญหา Nice Ruby ทำให้มันง่าย :-) (+1)
Platinum Azure

การทำให้มันเรียบง่ายไม่ใช่ข้ออ้างในการทำให้มันยาวเกินไปแม้ว่า ;-)
Joey

ฉันคิดว่าคุณสามารถแทนที่ 'if n == 0' ด้วย 'if! n'
Vincent

2
ในทับทิม? ฉันคิดเสมอว่าค่าทั้งหมดยกเว้นเท็จและศูนย์ประเมินเป็นจริง :-(
Platinum Azure

1

ลัวะ185 190 199

เพิ่มช่วงเวลาเพิ่ม io.read, ลบ () ในการพิมพ์ครั้งล่าสุด

 n=io.read();while(n~=4)do m=('43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:'):sub(n+1):byte()-48;print(n,' is ',m,'.')n=m;end print'4 is magic.'

ด้วยการแบ่งบรรทัด

 n=io.read()
 while (n~=4) do
    m=('43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:'):sub(n+1):byte()-48;
    print(n,' is ',m,'.')
    n=m;
 end 
 print'4 is magic.'

ต้องการn=io.read()(+11 ตัวอักษร) เพื่อให้สอดคล้องกับกฎเพื่ออ่านตัวเลขจากอินพุตมาตรฐาน การเปลี่ยนprint('4 is magic.')เป็นprint'4 is magic.'จะช่วยประหยัด 2 ตัวอักษร การถอด;หลังจากนั้น)จะช่วยประหยัด 1 ถ่าน การprintใช้เครื่องหมายจุลภาคดูเหมือนจะเป็นการโกง แต่ข้อมูลจำเพาะไม่ชัดเจน อาจเปลี่ยนเป็นprint(n,'is',m,'.')บันทึก 2 ตัวอักษรได้เช่นกัน
gwell

เครื่องหมายจุลภาคแสดงเป็นบรรทัดใหม่ใน Lua แบบสแตนด์อโลนหรือไม่ เป็นเวลานานแล้วที่ฉันใช้มัน
Nick Van Brunt

เครื่องหมายจุลภาคจะแสดงเป็นแท็บ
gwell

0

รหัส PhP

function get_num_name($num){  
    switch($num){  
        case 1:return 'one';  
    case 2:return 'two';  
    case 3:return 'three';  
    case 4:return 'four';  
    case 5:return 'five';  
    case 6:return 'six';  
    case 7:return 'seven';  
    case 8:return 'eight';  
    case 9:return 'nine';  
    }  
}  

function num_to_words($number, $real_name, $decimal_digit, $decimal_name){  
    $res = '';  
    $real = 0;  
    $decimal = 0;  

    if($number == 0)  
        return 'Zero'.(($real_name == '')?'':' '.$real_name);  
    if($number >= 0){  
        $real = floor($number);  
        $decimal = number_format($number - $real, $decimal_digit, '.', ',');  
    }else{  
        $real = ceil($number) * (-1);  
        $number = abs($number);  
        $decimal = number_format($number - $real, $decimal_digit, '.', ',');  
    }  
    $decimal = substr($decimal, strpos($decimal, '.') +1);  

    $unit_name[1] = 'thousand';  
    $unit_name[2] = 'million';  
    $unit_name[3] = 'billion';  
    $unit_name[4] = 'trillion';  

    $packet = array();    

    $number = strrev($real);  
    $packet = str_split($number,3);  

    for($i=0;$i<count($packet);$i++){  
        $tmp = strrev($packet[$i]);  
        $unit = $unit_name[$i];  
        if((int)$tmp == 0)  
            continue;  
        $tmp_res = '';  
        if(strlen($tmp) >= 2){  
            $tmp_proc = substr($tmp,-2);  
            switch($tmp_proc){  
                case '10':  
                    $tmp_res = 'ten';  
                    break;  
                case '11':  
                    $tmp_res = 'eleven';  
                    break;  
                case '12':  
                    $tmp_res = 'twelve';  
                    break;  
                case '13':  
                    $tmp_res = 'thirteen';  
                    break;  
                case '15':  
                    $tmp_res = 'fifteen';  
                    break;  
                case '20':  
                    $tmp_res = 'twenty';  
                    break;  
                case '30':  
                    $tmp_res = 'thirty';  
                    break;  
                case '40':  
                    $tmp_res = 'forty';  
                    break;  
                case '50':  
                    $tmp_res = 'fifty';  
                    break;  
                case '70':  
                    $tmp_res = 'seventy';  
                    break;  
                case '80':  
                    $tmp_res = 'eighty';  
                    break;  
                default:  
                    $tmp_begin = substr($tmp_proc,0,1);  
                    $tmp_end = substr($tmp_proc,1,1);  

                    if($tmp_begin == '1')  
                        $tmp_res = get_num_name($tmp_end).'teen';  
                    elseif($tmp_begin == '0')  
                        $tmp_res = get_num_name($tmp_end);  
                    elseif($tmp_end == '0')  
                        $tmp_res = get_num_name($tmp_begin).'ty';  
                    else{  
                        if($tmp_begin == '2')  
                            $tmp_res = 'twenty';  
                        elseif($tmp_begin == '3')  
                            $tmp_res = 'thirty';  
                        elseif($tmp_begin == '4')  
                            $tmp_res = 'forty';  
                        elseif($tmp_begin == '5')  
                            $tmp_res = 'fifty';  
                        elseif($tmp_begin == '6')  
                            $tmp_res = 'sixty';  
                        elseif($tmp_begin == '7')  
                            $tmp_res = 'seventy';  
                        elseif($tmp_begin == '8')  
                            $tmp_res = 'eighty';  
                        elseif($tmp_begin == '9')  
                            $tmp_res = 'ninety';  

                        $tmp_res = $tmp_res.' '.get_num_name($tmp_end);  
                    }  
                    break;  
            }  

            if(strlen($tmp) == 3){  
                $tmp_begin = substr($tmp,0,1);  

                $space = '';  
                if(substr($tmp_res,0,1) != ' ' && $tmp_res != '')  
                    $space = ' ';  

                if($tmp_begin != 0){  
                    if($tmp_begin != '0'){  
                        if($tmp_res != '')  
                            $tmp_res = 'and'.$space.$tmp_res;  
                    }  
                    $tmp_res = get_num_name($tmp_begin).' hundred'.$space.$tmp_res;  
                }  
            }  
        }else  
            $tmp_res = get_num_name($tmp);  
        $space = '';  
        if(substr($res,0,1) != ' ' && $res != '')  
            $space = ' ';  
        $res = $tmp_res.' '.$unit.$space.$res;  
    }  

    $space = '';  
    if(substr($res,-1) != ' ' && $res != '')  
        $space = ' ';  

    if($res)  
        $res .= $space.$real_name.(($real > 1 && $real_name != '')?'s':'');  

    if($decimal > 0)  
        $res .= ' '.num_to_words($decimal, '', 0, '').' '.$decimal_name.(($decimal > 1 && $decimal_name != '')?'s':'');  
    return ucfirst($res);  
}  

//////////// การทดสอบ ////////////////

 $str2num = 12;
    while($str2num!=4){
        $str = num_to_words($str2num, '', 0, '');  
        $str2num = strlen($str)-1;
        echo $str . '=' . $str2num .'<br/>';
        if ($str2num == 4)
            echo 'four is magic';
    }

////// ผล /////////

Twelve =6
Six =3
Three =5
Five =4
four is magic

4
@wallacoloo: วิธีแก้ปัญหาสำหรับภาษา crummy: D
Thomas Eding

5
หรือสั้นกว่ามาก 178 อักขระ:$l='4335443554366887798866555766';for($b=(int)fgets(fopen('php://stdin','r'));($a=$b)-4;){$b=$a<20?$l[$a]:$l[18+$a/10]+($a%10?$l[$a%10]:0);echo"$a is $b.\n";}echo"4 is magic.\n";
gnarf

ตลกดี. :-D โปรแกรมดีมาก
Tom Pažourek

0

Perl - 130 ตัวอักษร


5.12.1 (130 ตัวอักษร) 121 123 132 136 140

#        1         2         3         4         5         6         7         8         9        100        11        12        13       14    
#23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123

@u='4335443554366887798866555766'=~/./g;$_=pop;say"$_ is ",$_=$_-4?$_<20?$u[$_]:$u[$_/10+18]+(($_%=10)&&$u[$_]):magic,"."until/\D/


5.10.1 (134 ตัวอักษร) 125 127 136 140 144

#        1         2         3         4         5         6         7         8         9        100        11        12        13       14    
#23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234

@u='4335443554366887798866555766'=~/./g;$_=pop;print"$_ is ",$_=$_-4?$_<20?$u[$_]:$u[$_/10+18]+(($_%=10)&&$u[$_]):magic,".\n"until/\D/


ประวัติการเปลี่ยนแปลง:

20100714:2223- เปลี่ยนกลับตามความสนใจของmobruleแต่($_%10&&$u[$_%10])(($_%=10)&&$u[$_])ซึ่งเป็น # ตัวอักษรเดียวกัน แต่ฉันทำไปแล้วในกรณีที่อาจมีคนเห็นวิธีปรับปรุง

20100714:0041- split//,'...''...'=~/./g
20100714:0025- ($_%10&&$u[$_%10])$u[$_%10]
20100713:2340- while$_until/\D/+ ลบวงเล็บที่ไม่จำเป็นออก
20100713:xxxx- $=<>;chop;$_=pop;- เอื้อเฟื้อต่อmobrule


หมายเหตุ:ฉันเบื่อที่จะปรับปรุงคำตอบของคนอื่นในความคิดเห็นดังนั้นตอนนี้ฉันรู้สึกโลภและสามารถเพิ่มการเปลี่ยนแปลงของฉันได้ที่นี่ :) นี่คือส่วนที่แยกออกจากคำตอบของPlatinum Azure - เครดิตในส่วนของHobbs , mobruleและลาตินั่มสีฟ้า


เมื่อคุณกำจัด$_%10&&...โครงสร้างคุณทำลายข้อมูลจำเพาะสำหรับอินพุต 20,30,40, ...
ม็อบ

+1 ทำได้ดีมาก คุณออกจาก stdin ไปเป็น args แล้ว :-(
Platinum Azure

ถูกแทนที่ด้วยARGVซึ่งบรรจุโดยSTDIN:) หรือ .. echo bar | xargs perl foo.plในทางเทคนิค piped จาก echo ไปยัง args สำหรับ perl :)
vol7ron

0

Perl ไร้ยางอายพร้อมคำจำนวน (329 ตัวอักษร)

ดัดแปลงมาจากรหัส C ของ P Daddy โดยตรงโดยมีการปรับแต่งบางอย่างp()เพื่อให้ทำสิ่งเดียวกันโดยใช้ Perl primitives แทน C และ mainloop ที่เขียนใหม่ส่วนใหญ่ ดูคำอธิบายของเขา Newlines เป็นทางเลือกทั้งหมด

@t=(qw(zero one two three four five six sM eight nine
tL elM twelve NP 4P fifP 6P 7P 8O 9P twLQ NQ forQ fifQ
6Q 7Q 8y 9Q en evL thir eL tO ty 4SmagicT)," is ",".\n");
sub p{local$_=$t[pop];1while s/[0-Z]/$t[-48+ord$&]/e;
print;length}$_=<>;chop;while($_-4){
$_=($_>19?(p($_/10+18),$_&&print("-"),$_%=10)[0]:0)+p$_;
p 35;p$_;p 36}p 34

หมายเหตุด้านข้าง: มันแย่เกินไปที่ perl printจะคืนค่าจริง / เท็จ ถ้ามันส่งคืนการนับมันจะช่วยฉันได้ 7 จังหวะ


0

ทับทิม 141 ตัวอักษร:

n=gets.to_i;m="4335443554366887798866555766";loop{s=n;n=n>20?m[18+n/10]+m[n%10]-96: m[n]-48;puts"#{s} is #{n==s ? 'magic': n}.";n==s &&break}

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