ภาพยนตร์เรื่อง“ Deaf Grandma” ของ Chris Pine


22

ฉันเป็นที่ปรึกษาของ RubyLearning และหนึ่งในแบบฝึกหัดที่เรามอบให้กับนักเรียนของเราคือแบบฝึกหัด "คนหูหนวกคุณยาย" จากหนังสือของ Chris Pine " Learn to Program " นี่คือคำอธิบาย:

เขียนโปรแกรม Deaf Grandma ไม่ว่าคุณจะพูดอะไรกับคุณย่า (ไม่ว่าคุณจะพิมพ์อะไร) เธอควรตอบด้วย: "อืม?! พูดออกมานี่ซันนี่!" เว้นแต่คุณจะตะโกน (พิมพ์ทุกประเภท) หากคุณตะโกนเธอจะได้ยินคุณ (หรืออย่างน้อยเธอก็คิดอย่างนั้น) และตะโกนกลับมาว่า: "ไม่ไม่ใช่ตั้งแต่ปี 1938!"

เพื่อให้โปรแกรมของคุณน่าเชื่อถือจริงๆให้คุณยายตะโกนปีละครั้งกัน อาจสุ่มปีใดก็ได้ระหว่างปี 1930 ถึง 1950 (ส่วนนี้เป็นทางเลือกและจะง่ายกว่ามากถ้าคุณอ่านส่วนของตัวสร้างหมายเลขสุ่มของ Ruby ที่ท้ายบทวิธี) คุณไม่สามารถหยุดคุยกับคุณยายจนกว่าคุณจะ ตะโกน "BYE"

หลังจากทำซ้ำหลายคอร์สฉันพยายามดูว่าฉันจะได้ขนาดเล็กแค่ไหนและตอนนี้มีอักขระได้ถึง 112 ตัว:

puts (s||='').upcase==s ? "NO, NOT SINCE #{1930+rand(21)}!":"HUH?! SPEAK UP, SONNY!" until(s=gets.chomp)=="BYE"

ฉันอยากรู้ว่าตัวละครสองสามตัวนี้สามารถทำได้ในภาษาที่คุณเลือกเพราะฉันคิดว่ารูบี้ทำได้ดีมากที่นี่

แก้ไข:โซลูชัน Perl ที่โพสต์ด้านล่างนำไปสู่

ruby -nle 'puts($_=="BYE"?exit: $_.upcase!? "HUH?! SEPAK UP, SONNY!":"NO, NOT SINCE #{1930+rand(21)}!")'

ซึ่งคือ 92 อักขระสำหรับนิพจน์และอีก 2 รายการสำหรับตัวเลือกnและl


ในบริบทของการเล่นกอล์ฟสิ่งนี้ต้องการข้อมูลจำเพาะเพิ่มเติม จะเกิดอะไรขึ้นถ้าหากมี BYE มากกว่าปกติ?
JB

เฉพาะ "BYE" เท่านั้นที่ยกเลิกโปรแกรม
Michael Kohl

คำตอบ:


13

Perl, 85 91

ทำงานด้วยperl -nE '<code goes there>'( nนับขนาดโปรแกรม):

$==1930+rand 21;say/^BYE$/?last:uc eq$_?"
NO, NOT SINCE $=!":"HUH?! SPEAK UP, SONNY!"

เครื่องหมายอัศเจรีย์ท้ายดังกล่าวมีราคาแพงมาก ...

การแก้ไขที่แนะนำโดย IK:

  • การใช้ regexp แทนการจับคู่สตริงจะ-lสำรองตัวเลือกโกลบอลรวมทั้งอักขระโปรแกรมสองตัว: -3
  • การใช้ตัวแปรจริงเพื่อบันทึกค่าและใช้ในภายหลังเพื่อการแก้ไข (Genius! ใครจะนึกถึงการใช้ตัวแปรสำหรับสิ่งนั้น?): 0
  • ทำให้ตัวแปร$=นั้นถูก จำกัด ให้เป็นจำนวนเต็ม: -4

(และมันยังไม่เพิ่มขึ้นและฉันง่วงเกินไปที่จะหาสาเหตุว่าทำไมอืมการนับขั้นสุดท้ายถูกต้องอย่างน้อย)


การ$=ใช้ผิดวิธีและใช้ regexp สำหรับ "BYE" ทำให้สิ่งนี้ลดลงเป็น 84 + 1:perl -nE '$==1930+rand 21;say/^BYE$/?last:uc eq$_?"NO, NOT SINCE $=!":"HUH?! SPEAK UP, SONNY!"'
Ilmari Karonen

@IlmariKaronen บูรณาการขอบคุณ!
JB

6

Python 120 ตัวอักษร

r=raw_input
s=r()
while'BYE'!=s:
 print["HUH?! SPEAK UP, SONNY!","NO, NOT SINCE %d!"%(1930+id(s)%21)][s.isupper()];s=r()

คำแนะนำใด ๆ ในการปรับปรุง?


คุณไม่จำเป็นต้องใส่เครื่องหมายวงเล็บถ้าคุณมีคำสั่งฉันก็ค่อนข้างมั่นใจว่าหลามมีเพดานการเรียกซ้ำ - แต่นั่นอาจเป็นการจำลองสถานการณ์ของคุณยายที่กำลังหลับอยู่
Phoshi

Oh! ฉันลืมที่จะลบวงเล็บ ขอบคุณ :)
fR0DDY

คุณสามารถบันทึกตัวละครบางตัวได้ถ้าคุณลบบรรทัดแรกแทนที่ตัวที่สองด้วยs=''เรียงลำดับคำสั่งของคุณใหม่อีกครั้งใน loop ของคุณและวางทั้งวงขณะที่หนึ่งบรรทัด: gist.github.com/3787809หากคุณตั้งใจจริง ๆ คุณสามารถ บันทึก 2 ตัวอักษรโดยใช้ python 3 (raw_input () -> input () แต่ print -> print ())
Matt

4

131 อักขระใน PowerShell:

for(){$j=read-host;if($j-ceq"BYE"){break}if($j-ceq$j.ToUpper()){"No, not since 19$(10..90|random)!"}else{"Huh?! Speak up, sonny!"}}

W / ช่องว่าง:

for(){
  $j = read-host;
  if ( $j -ceq "BYE" ) { break }
  if ( $j -ceq $j.ToUpper() ) { "No, not since 19$(10..90|random)!" }
  else { "Huh?! Speak up, sonny!" }
}

บีบตัวละคร 18 ตัวจากคำแนะนำของ Joey

BTW 'Learn to Program' เป็นหนังสือการเขียนโปรแกรมเล่มแรกที่ฉันเคยอ่านหน้าปก


คุณอาจต้องการดูที่นี่: codegolf.stackexchange.com/questions/191/…
Joey

คุณสามารถทำให้มันลดลงไปที่ 120 ได้โดยการบีบแรกif...เข้าไปในการตรวจสอบตามเงื่อนไขของสิ่งfor()นั้น: for(;($j=read-host)-cne"BYE"){if($j-ceq$j.ToUpper()){...นอกจากนี้สเป็คบอกว่า 1930-1950
SpellingD

3

C # - 234 ตัวอักษร

using System;class P{static void Main(){for(;;){var s=Console.ReadLine();if(s!=s.ToUpper()){Console.WriteLine("Huh?! Speak up, sonny!");continue;}if(s=="BYE")break;Console.WriteLine("No, not since 19{0}!",new Random().Next(30,51));}}}

อ่านเพิ่มเติมได้:

using System;
class P
{
    static void Main()
    {
        for(;;)
        {
            var s=Console.ReadLine();
            if(s!=s.ToUpper())
            {
                Console.WriteLine("Huh?! Speak up, sonny!");
                continue;
            }
            if(s=="BYE")
                break;
            Console.WriteLine("No, not since 19{0}!",new Random().Next(30,51));
        }
    }
}

อาคิดถึงคนง่าย ๆ ในเหมืองและทำผิดพลาดไปบ้าง Nice +1
Kyle Rozendo

3

Befunge - 27x6 = 162 ตัวอักษร

> ~:0`  #v _            vv<
         >:"a"`!#v  _:"z"`|
^                <       <
v"Huh?! Speak up, sonny!"0<
v"No, not since 1938!"0 <
>:# #, _@

แก้ไข: พลาดส่วน "BYE" โดยสิ้นเชิง เวอร์ชั่นใหม่เร็ว ๆ นี้

แก้ไข 2: จริง ๆ แล้วมันทำให้ซับซ้อนเกินไปสำหรับทักษะ Befunge ที่น้อยของฉัน ฉันอาจลองอีกครั้งในภายหลัง แต่ฉันไม่สามารถนึกถึงวิธีง่ายๆในการใช้งานได้ในขณะนี้


3

C # - 194 CHARS

using System;class P{static void Main(){var s=Console.ReadLine();if(s!="BYE"){Console.Write((s==s.ToUpper()?"No, not since 19"+new Random().Next(30, 51):"Huh?! Speak up, sonny")+"!");Main();}}}

ด้วยช่องว่าง:

using System;
class P
{
    static void Main()
    {
        var s = Console.ReadLine();
        if (s != "BYE")
        {
            Console.Write((s == s.ToUpper() ? "No, not since 19" + new Random().Next(30, 51) : "Huh?! Speak up, sonny") + "!");
            Main();
        }
    }
}

ด้วยแรงบันดาลใจบางส่วนจาก Nellius และ fR0DDY

โปรดแจ้งให้เราทราบหากสามารถปรับปรุงได้


สั้น แต่ FWIW ฉันคิดว่านี่รั่ว (โทรซ้ำMain()) นอกจากนี้ฉันคิดว่าคุณต้องการ parens ในการ?:แสดงออกเพื่อให้ได้!ทั้ง ฉันเพิ่มคำตอบด้วยสิ่งนี้และ EOL (แต่ก็ยังรั่วไหล)
bw

ฉันเห็นคุณเพิ่ม parens และลบความคิดเห็นของคุณ ทำได้ดีมาก ตอนนี้การแก้ไขของฉันเพื่อเพิ่มภาพหน้าจอในคำตอบที่มีและไม่มี parens คือสิ่งที่สงสัย (แต่ก็ยังรั่วอยู่) :-)
bw

@ บิลใช่ฉันทำการทดสอบในตอนแรก รุ่นรั่วไม่ใช่จะเป็น 199 ตัวอักษร, waaay นานเกินไป :)
ริชาร์ด

ฮ้า ฉันชอบMain();วิธีแก้ปัญหา ... ไม่มีคนที่มีสติจะใช้โปรแกรมนี้นานพอที่จะเป็นปัญหา
bw

ในฐานะที่เป็น Phoshi กล่าวในความคิดเห็นเพื่อ fR0DDY โปรแกรมขัดข้องเมื่อคุณยายหลับ
Richard

3

D: 246 ตัวละคร

import std.random,std.stdio,std.string;void main(){auto r=rndGen();for(;;){auto t=strip(readln());if(t=="BYE")break;if(t.toupper()==t)writefln("No, not since %s!",{r.popFront();return r.front%20+1930;}());else writeln("Huh?! Speak up, sonny!");}}

ชัดเจนยิ่งขึ้น:

import std.random, std.stdio, std.string;

void main()
{
    auto r = rndGen();

    for(;;)
    {
        auto t = strip(readln());

        if(t == "BYE")
            break;

        if(t.toupper() == t)
            writefln("No, not since %s!", {r.popFront(); return r.front % 20 + 1930;}());
        else
            writeln("Huh?! Speak up, sonny!");
    }
}

3

จาวาสคริปต์, 142 ตัวอักษร, 29 ตัวในการสุ่มปี

n='a'; while((/[a-z]/.test(n)?r="HUH?! SPEAK UP, SONNY!":n=="BYE"?r='':r="NO, NOT SINCE "+Math.floor(Math.random()*21+1930))!=''){n=prompt(r)}


3

Windows PowerShell, 121 117

เนื่องจากลักษณะของงานสิ่งนี้จึงดูคล้ายกับโซลูชันของ Ty Auvilถึงแม้ว่ามันจะถูกเขียนขึ้นอย่างอิสระ:

for(;($j=read-host)-cne'BYE'){if($j-cmatch'[a-z]'){'Huh?! Speak up, sonny!'}else{"No, not since 19$(30..50|random)"}}

ขอบคุณ SpellingD สำหรับคำแนะนำ


ฉันชอบการจับคู่ regex ของคุณ แต่คำสั่ง switch นั้นใหญ่มาก พร้อมกับข้อเสนอแนะที่ฉันให้ Ty คุณสามารถลดจำนวนตัวละครของคุณเป็น 117 ได้โดยใช้ regex ifแทนแบบนี้:for(;($j=read-host)-cne'BYE'){if($j-cmatch'[a-z]'){'Huh?! Speak up, sonny!'}else{"No, not since 19$(30..50|random)"}}
SpellingD

2

Haskell (189)

import Random
import Char
main=getLine>>=g
g"BYE"=return""
g s|s/=map toUpper s=putStrLn"HUH?! SPEAK UP SONNY!">>main|4>2=randomRIO(30,50::Int)>>=putStrLn.("NO, NOT SINCE 19"++).show>>main

สิ่งที่แปลกคือรหัส Haskell มักจะสั้นกว่าโค้ด C มากเมื่อเทียบกับการเขียนโปรแกรม 'จริงจัง'


คุณสามารถหลีกเลี่ยงการนำเข้าCharโดยใช้any(`elem`['a'..'z'])sเพื่อทดสอบอักษรตัวพิมพ์เล็ก
hammar


1

C # - 345 Chars

using System;class Program{static void Main(){for(;;){if(!t(Console.ReadLine()))break;}}static bool t(string s){bool b=false;if(s=="BYE")return b;int i=0;for(;i<s.Length;i++){b=(s[i]>65&&s[i]<90)?true:false;if(!b)break;}if(b) p("NO, NOT SINCE 1938!");else p("HUH?! SPEAK UP, SONNY!");return true;}static void p(string s){Console.WriteLine(s);}}

ภาษา verbose ประณาม ... :-)


1
คุณสามารถโทรหาชั้นเรียนPได้ และนี่ตรวจไม่พบตัวพิมพ์ใหญ่อย่างถูกต้อง ฉันสามารถตะโกนใส่มันและมันก็ยังไม่ได้ยินฉัน คุณสามารถย่อวิธีการหลักให้สั้นลงwhile(t(Console.ReadLine()));ได้ คุณสามารถใช้using C=System.Console;ที่เริ่มต้นเพื่อลดการเข้าถึงReadLine()และWriteLine()การและC.ReadLine() C.WriteLine()
Joey

@Joey - ขอบคุณสำหรับเคล็ดลับ!
Kyle Rozendo

1

C # - 196 ตัวอักษร (แต่รั่ว)

using System;class P{static void Main(){var s=Console.ReadLine();if(s!="BYE"){Console.Write((s==s.ToUpper()?"No, not since 19"+new Random().Next(30, 51):"Huh?! Speak up, sonny")+"!\n");Main();}}}

นั่นเป็นคำตอบที่ @ Richard's (รั่ว) โดยมีสอง parens (ดูด้านล่าง) และ a \ n ที่เพิ่มเข้ามาเพื่อรับ EOL ในทั้งสองกรณี มิฉะนั้น" + "จะเสียพื้นที่เพียง

ที่จัดรูปแบบ

using System;
class P
{
    static void Main() { 
        var s = Console.ReadLine(); 
        if (s != "BYE") { 
            Console.Write((
                s == s.ToUpper() ? 
                "No, not since 19" + new Random().Next(30, 51) : 
                "Huh?! Speak up, sonny"
                ) + "!\n");
            Main(); 
        } 
    }
}

UPDATE: เพื่อชี้แจงความคิดเห็นของฉันเกี่ยวกับ parens ที่ต้องการนี่คือสิ่งที่ฉันได้รับโดยไม่ต้อง parens (เช่นกับโซลูชันดั้งเดิมของ @ Richard):

โดยไม่ต้อง parens

และด้วยการล้อเลียน:

ด้วย parens

ทั้งสองอย่างนี้ใช้ของฉันเพิ่มเติม \nว่า


มันคือ 195 ที่นี่เท่านั้น คุณนับการขึ้นบรรทัดใหม่โดยไม่จำเป็นหรือไม่?
Joey

1

ทุบตี: 136 128 ตัวอักษร

while read s
do
[[ $s = BYE ]]&&break
[[ ${s^^} = $s ]]&&echo NO, NOT SINCE $[RANDOM%21+1930]!||echo HUH?! SPEAK UP, SONNY!
done

ทางเลือก จำกัด : 132 123 ตัวอักษร

f(){
read s
[[ $s = BYE ]]||{
[[ ${s^^} = $s ]]&&echo NO, NOT SINCE $[RANDOM%21+1930]!||echo HUH?! SPEAK UP, SONNY!
f
}
}
f

คุณสามารถพูดคุยกับคนหูหนวกไม่ จำกัด แต่การสนทนาด้วยรหัสในภายหลังนี้ถูก จำกัด โดยสายเรียกซ้อน (ในการทดสอบของฉันมันจะถูกยกเลิกหลังจาก 4989 สาย)


1

Javascript - 133 131 130 128 127 121 ตัวอักษร

โซลูชั่น www0z0ks รุ่น golfed

g='';while((i=prompt(g))!='BYE'){/[a-z]/.test(i)?g='Huh?! Speak up, sonny!':g='No, not since '+Math.floor(Math.random()*21+1930)+'!'}

g='';while((i=prompt(g))!='BYE'){g=/[a-z]/.test(i)?'Huh?! Speak up, sonny!':'No, not since '+Math.floor(Math.random()*21+1930)+'!'}

g='';while((i=prompt(g))!='BYE'){g=/[a-z]/.test(i)?'Huh?! Speak up, sonny!':'No, not since '+Math.ceil(Math.random()*21+1929)+'!'}

for(g='';(i=prompt(g))!='BYE';g=/[a-z]/.test(i)?'Huh?! Speak up, sonny!':'No, not since '+Math.ceil(Math.random()*21+1929)+'!');

for(g='';(i=prompt(g))!='BYE';g=/[a-z]/.test(i)?'Huh?! Speak up, sonny!':'No, not since '+parseInt(Math.random()*21+1930)+'!');

for(g='';(i=prompt(g))!='BYE';g=/[a-z]/.test(i)?'Huh?! Speak up, sonny!':'No, not since '+(Math.random()*21+1930|0)+'!');

แก้ไข:บันทึกอีกหกตัวอักษรด้วยเคล็ดลับที่ยอดเยี่ยมนี้


เขียนผู้ประกอบการที่ประกอบไปด้วยg=/[a-z]/.test(i)?'Huh?!...':'No...'และคุณสำรองอักขระ 2 ตัว
จัดการ

แก้ไขแล้วขอบคุณสำหรับตัวชี้
codeporn

1
รายละเอียดเพิ่มเติม 1 ตัวละครที่ฉันพบ: สั้นกว่าMath.ceil() เพียงแค่เปลี่ยนปีฐานเพื่อให้ช่วงเวลาที่ไม่เปลี่ยนแปลง:Math.floor() Math.ceil(Math.random()*21+1929)
จัดการ

ยอดเยี่ยม +1! ฉันบันทึกอีกสองตัวอักษรด้วยการเปลี่ยนขณะที่เป็นห่วง
codeporn

0

Clojure - 160 154 ตัวอักษร

(#(if(= % "BYE")%(do(if(=(.toUpperCase %)%)(prn(str"No, not since "(+ 1930(rand-int 9))"!"))(prn"Huh?! Speak up, sonny!"))(recur(read-line))))(read-line))

ทำงานเกี่ยวกับการเล่นกอล์ฟให้มากขึ้น ยินดีต้อนรับข้อเสนอแนะ

วิ่งผ่าน REPL


0

คำถามที่ 115

{while[1;v:read0 0;$[v~"BYE";'`;v~upper v;-1"No, not since ",/:(($)1?1930+(!)20),'"!";-1"Huh?! Speak up, sonny!"]]}

การใช้

q){while[1;v:read0 0;$[v~"BYE";'`;v~upper v;-1"No, not since ",/:(($)1?1930+(!)20),'"!";-1"Huh?! Speak up, sonny!"]]}`
Hi
Huh?! Speak up, sonny!
Hello
Huh?! Speak up, sonny!
HELLO!
No, not since 1938!
Goodbye Grandma
Huh?! Speak up, sonny!
BYE
'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.