“Nenek Tuli” Chris Pine

22

Saya seorang mentor di RubyLearning dan salah satu latihan yang kami berikan kepada siswa kami adalah latihan "Tuna Rungu" dari buku Chris Pine, " Learn to Program ". Berikut uraiannya:

Tulis program Nenek Tuli. Apa pun yang Anda katakan kepada nenek (apa pun yang Anda ketikkan), ia harus menjawab dengan: "Hah ?! Bicaralah, Nak!", Kecuali Anda meneriakkannya (ketikkan semua huruf besar). Jika Anda berteriak, dia bisa mendengarmu (atau setidaknya menurutnya begitu) dan berteriak: "Tidak, tidak sejak 1938!"

Untuk membuat program Anda benar-benar dapat dipercaya, mintalah nenek berteriak tahun yang berbeda setiap kali; mungkin setiap tahun secara acak antara 1930 dan 1950. (Bagian ini opsional, dan akan jauh lebih mudah jika Anda membaca bagian tentang penghasil angka acak Ruby di akhir bab metode.) Anda tidak dapat berhenti berbicara dengan nenek sampai Anda teriak "BYE".

Setelah beberapa kali pengulangan, saya mencoba melihat seberapa kecil saya bisa mendapatkan ini dan sekarang memilikinya hingga 112 karakter:

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

Saya ingin tahu seberapa sedikit karakter ini dapat dicapai dalam bahasa pilihan Anda, karena saya pikir Ruby sudah melakukannya dengan sangat baik di sini.

Sunting: Solusi Perl yang diposting di bawah ini mengarah ke

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

yang merupakan 92 karakter untuk ekspresi + 2 lebih banyak untuk opsi ndan l.

Michael Kohl
sumber
Dalam konteks golf, ini membutuhkan spesifikasi tambahan. Apa yang harus terjadi jika ada keluaran tambahan yang melewati BYE?
JB
Hanya "BYE" yang benar-benar menghentikan program.
Michael Kohl

Jawaban:

13

Perl, 85 91

Jalankan dengan perl -nE '<code goes there>'( ndihitung dalam ukuran program):

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

Tanda seru itu sangat mahal ...

Suntingan yang disarankan oleh IK:

  • Menggunakan regexp alih-alih pencocokan string memberikan -lopsi global serta dua karakter program: -3.
  • Menggunakan variabel aktual untuk menyimpan nilai dan menggunakannya nanti untuk interpolasi (Genius! Siapa yang berpikir untuk menggunakan variabel untuk itu?): 0.
  • Membuat variabel itu $=, dibatasi menjadi bilangan bulat: -4.

(Dan itu masih belum sesuai dan saya terlalu mengantuk untuk mencari tahu mengapa. Oh well, hitungan terakhir setidaknya benar)

JB
sumber
Menyalahgunakan $=dan menggunakan regexp untuk "BYE" akan menurunkannya menjadi 84 + 1:perl -nE '$==1930+rand 21;say/^BYE$/?last:uc eq$_?"NO, NOT SINCE $=!":"HUH?! SPEAK UP, SONNY!"'
Ilmari Karonen
@IlmariKaronen Terintegrasi, terima kasih!
JB
6

Python 120 Karakter

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

Ada petunjuk untuk diperbaiki?

fR0DDY
sumber
Anda tidak perlu tanda kurung di sekitar itu jika pernyataan, juga saya cukup yakin python memiliki langit-langit rekursi - tetapi itu bisa saja mensimulasikan nenek Anda tertidur.
Phoshi
Oh! Saya lupa menghapus tanda kurung. Terima kasih :)
fR0DDY
Anda dapat menyimpan beberapa karakter jika Anda menghapus baris pertama, ganti baris kedua dengan s='', menyusun ulang pernyataan Anda di loop sementara Anda, dan menempatkan keseluruhan loop sementara pada satu baris: gist.github.com/3787809 Jika Anda benar-benar ditentukan, Anda bisa simpan 2 karakter dengan menggunakan python 3 (raw_input () -> input (), tetapi cetak -> print ())
Matt
4

131 karakter di 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 / spasi putih:

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!" }
}

Meremas 18 karakter dari saran Joey.

BTW, 'Belajar Program' adalah buku pemrograman pertama yang pernah saya baca sampul depan.

Ty Auvil
sumber
Anda mungkin ingin melihatnya di sini: codegolf.stackexchange.com/questions/191/…
Joey
Anda bisa mendapatkan ini ke 120 dengan memasukkan yang pertama if...ke dalam pemeriksaan bersyarat for()seperti ini: for(;($j=read-host)-cne"BYE"){if($j-ceq$j.ToUpper()){...Juga, spesifikasi mengatakan 1930-1950.
SpellingD
3

C # - 234 Chars

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

Lebih mudah dibaca:

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));
        }
    }
}
Nellius
sumber
Ah ketinggalan beberapa yang sederhana di milikku, dan membuat beberapa kesalahan konyol. Bagus +1
Kyle Rozendo
3

Befunge - 27x6 = 162 karakter

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

EDIT: Benar-benar melewatkan bagian "BYE". Versi baru segera hadir.

EDIT 2: Sebenarnya, itu membuatnya agak terlalu rumit untuk keterampilan Befunge saya yang sedikit. Saya mungkin mencoba lagi nanti, tetapi saya tidak bisa memikirkan cara sederhana untuk mengimplementasikannya saat ini.

Nemo157
sumber
3

C # - 194 BIAYA

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

Dengan spasi putih:

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

Dengan beberapa inspirasi dari Nellius dan fR0DDY.

Tolong beri tahu saya jika itu dapat ditingkatkan.

Richard
sumber
Singkat, tapi FWIW, saya pikir ini bocor (panggilan rekursif Main()). Juga, saya pikir Anda ingin orangtua dalam ?:ekspresi untuk mendapatkan !keduanya. Saya menambahkan jawaban dengan ini dan EOL (tapi masih bocor).
bw
saya melihat Anda menambahkan parens dan menghapus komentar Anda. Kerja bagus. Sekarang edit saya untuk menambahkan tangkapan layar untuk jawaban saya dengan dan tanpa parens sedang diperdebatkan. (Tapi, masih bocor) :-)
bw
@ bill Ya, saya mengacaukan pengujian saya awalnya. Versi yang tidak bocor adalah 199 karakter, terlalu lama :)
Richard
Ha. Saya suka Main();solusinya ... tidak ada orang waras yang akan menggunakan program ini cukup lama untuk itu menjadi masalah.
bw
Seperti yang dikatakan Phoshi dalam komentar kepada fR0DDY. Program macet ketika nenek tertidur.
Richard
3

D: 246 Karakter

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

Lebih Jelas:

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!");
    }
}
Jonathan M Davis
sumber
3

javascript, 142 karakter, 29 di antaranya melakukan tahun acak

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)}
www0z0k
sumber
3

Awk: 97 karakter

$0=="BYE"{exit}$0=toupper($0)==$0?"NO, NOT SINCE "int(rand()*21+1930)"!":"HUH?! SPEAK UP, SONNY!"
manatwork
sumber
3

Windows PowerShell, 121 117

Karena sifat tugas ini terlihat cukup identik dengan solusi Ty Auvil , meskipun ditulis secara independen:

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

Terima kasih kepada SpellingD untuk sarannya,

Joey
sumber
Saya suka pencocokan regex Anda, tetapi pernyataan switchnya terlalu besar. Bersamaan dengan saran yang saya berikan kepada Ty, Anda dapat mengurangi jumlah karakter Anda menjadi 117 dengan menggunakan regex dengan ifgantinya seperti ini: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

Yang aneh adalah, kode Haskell biasanya jauh lebih pendek daripada kode C yang sebanding ketika menulis program 'serius'.

marinus
sumber
Anda dapat menghindari impor Chardengan menggunakan any(`elem`['a'..'z'])suntuk menguji huruf kecil.
hammar
2

APL (76)

 {'BYE'≢A←⍞:∇⎕←{∧/⍵∊⎕A:'No, not since ',⍕1938+?20⋄'Huh?! Speak up sonny!'}A}⍬
marinus
sumber
1

C # - 345 Karakter

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

Bahasa kasar sialan: :-)

Kyle Rozendo
sumber
1
Anda bisa memanggil kelas saja P. Dan ini tidak mendeteksi huruf besar dengan benar. Saya bisa berteriak dan masih tidak bisa mendengar saya. Anda dapat mempersingkat metode utama menjadi while(t(Console.ReadLine()));. Anda dapat menggunakan using C=System.Console;di awal untuk mempersingkat akses ke ReadLine()dan WriteLine()ke C.ReadLine()dan C.WriteLine().
Joey
@ Joey - Terima kasih atas tipsnya!
Kyle Rozendo
1

C # - 196 karakter (tapi bocor)

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

Itu @ Richard's (bocor) jawaban dengan dua parens (lihat di bawah) dan a \ n ditambahkan di sana untuk mendapatkan EOL dalam kedua kasus. Kalau tidak, " + "hanya ruang terbuang.

Diformat

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: untuk mengklarifikasi komentar saya tentang parens yang diperlukan, inilah yang saya dapatkan tanpa parens (yaitu dengan solusi asli @ Richard):

tanpa orangtua

Dan dengan parens:

dengan parens

Tak satu pun dari ini menggunakan tambahan saya \n.

bw
sumber
Ini 195 di sini, hanya. Apakah Anda menghitung jeda baris yang tidak perlu di akhir?
Joey
1

Bash: 136 128 karakter

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

Alternatif terbatas: 132 123 karakter

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

Anda dapat berbicara dengan tuli tanpa batas, tetapi percakapan dengan kode nanti dibatasi oleh tumpukan panggilan. (Dalam pengujian saya akan dihentikan setelah 4989 panggilan.)

manatwork
sumber
1

Javascript - 133 131 130 128 127 121 karakter

versi golf dari solusi www0z0ks

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)+'!');

Sunting: Menyimpan enam karakter lainnya dengan tip hebat ini

codeporn
sumber
Tulis operator ternary sebagai g=/[a-z]/.test(i)?'Huh?!...':'No...'dan Anda menyimpan 2 karakter.
manatwork
Diedit, terima kasih atas penunjuknya.
codeporn
1
1 lebih banyak karakter yang saya temukan: Math.ceil()lebih pendek dari Math.floor(). Hanya mengubah tahun dasar untuk menjaga interval tidak berubah: Math.ceil(Math.random()*21+1929).
manatwork
Hebat, +1! Saya menyimpan dua karakter lain dengan mengubah while menjadi for for.
codeporn
0

Clojure - 160 154 Karakter

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

Bekerja untuk bermain golf sedikit lebih. Saran diterima.

Jalankan melalui REPL

TuanZander
sumber
0

Q, 115

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

pemakaian

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
'
tmartin
sumber