Chris Thông của người điếc Bà điếc Bà


22

Tôi là một người cố vấn tại RubyLearning và một trong những bài tập chúng tôi dành cho học sinh của mình là bài tập "Điếc bà" từ cuốn sách " Học cách lập trình " của Chris Pine . Đây là mô tả:

Viết một chương trình Bà Điếc. Bất cứ điều gì bạn nói với bà (bất cứ điều gì bạn nhập vào), cô ấy nên trả lời: "Hả?! Hãy lên tiếng, con trai!", Trừ khi bạn hét lên (gõ vào tất cả các chữ viết hoa). Nếu bạn hét lên, cô ấy có thể nghe thấy bạn (hoặc ít nhất là cô ấy nghĩ vậy) và hét lại: "Không, không kể từ năm 1938!"

Để làm cho chương trình của bạn thực sự đáng tin cậy, hãy để bà nội hét lên một năm khác nhau mỗi lần; có thể bất kỳ năm nào ngẫu nhiên trong khoảng thời gian từ 1930 đến 1950. (Phần này là tùy chọn và sẽ dễ dàng hơn nhiều nếu bạn đọc phần trên trình tạo số ngẫu nhiên của Ruby ở cuối chương phương pháp.) Bạn không thể ngừng nói chuyện với bà cho đến khi bạn hét lên "BYE".

Sau vài lần lặp lại khóa học, tôi đã cố gắng xem tôi có thể có được cái này nhỏ đến mức nào và bây giờ có tới 112 ký tự:

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

Tôi tò mò muốn xem làm thế nào ít nhân vật này có thể đạt được bằng ngôn ngữ bạn chọn, bởi vì tôi nghĩ Ruby đã làm rất tốt ở đây.

Chỉnh sửa: Giải pháp Perl được đăng dưới đây dẫn đến

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

đó là 92 ký tự cho biểu thức + 2 thêm cho các tùy chọn nl.


Trong một bối cảnh chơi golf, điều này cần đặc điểm kỹ thuật bổ sung. Điều gì sẽ xảy ra nếu có bất kỳ đầu ra bổ sung nào qua BYE?
JB

Chỉ "BYE" chính xác chấm dứt chương trình.
Michael Kohl

Câu trả lời:


13

Perl, 85 91

Chạy với perl -nE '<code goes there>'( ntính theo kích thước chương trình):

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

Dấu chấm than đó rất đắt ...

Các chỉnh sửa được đề xuất bởi IK:

  • Sử dụng biểu thức chính quy thay vì khớp chuỗi sẽ bỏ qua -ltùy chọn chung cũng như hai ký tự chương trình: -3.
  • Sử dụng một biến thực tế để lưu một giá trị và sử dụng nó sau này để nội suy (Genius! Ai đã nghĩ đến việc sử dụng một biến cho điều đó?): 0.
  • Tạo biến đó $=, bị ràng buộc là một số nguyên: -4.

(và nó vẫn không thêm và tôi quá buồn ngủ để tìm hiểu lý do tại sao. Ồ, số lượng cuối cùng là đúng ít nhất)


Việc lạm dụng $=và sử dụng biểu thức chính quy cho "BYE" sẽ giảm xuống còn 84 + 1:perl -nE '$==1930+rand 21;say/^BYE$/?last:uc eq$_?"NO, NOT SINCE $=!":"HUH?! SPEAK UP, SONNY!"'
Ilmari Karonen

@IlmariKaronen Tích hợp, cảm ơn!
JB

6

Python 120 ký tự

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

Bất kỳ gợi ý để cải thiện?


Bạn không cần dấu ngoặc xung quanh câu lệnh if đó, tôi cũng chắc chắn rằng con trăn có trần đệ quy - nhưng điều đó chỉ có thể mô phỏng bà của bạn ngủ thiếp đi.
Phoshi

Oh! Tôi quên xóa dấu ngoặc. Cảm ơn :)
fR0DDY

Bạn có thể lưu một số ký tự nếu bạn xóa dòng đầu tiên, thay thế dòng thứ hai bằng s='', sắp xếp lại các câu lệnh trong vòng lặp while của bạn và đặt toàn bộ vòng lặp while trên một dòng: gist.github.com/3787809 Nếu bạn thực sự quyết tâm, bạn có thể lưu 2 ký tự bằng cách sử dụng python 3 (raw_input () -> input (), nhưng in -> print ())
Matt

4

131 ký tự trong 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 / khoảng trắng:

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

Bóp 18 ký tự từ đề nghị của Joey.

BTW, 'Tìm hiểu chương trình' là cuốn sách lập trình đầu tiên tôi từng đọc trang bìa.


Bạn có thể muốn xem tại đây: codegolf.stackexchange.com/questions/191/ mẹo
Joey

Bạn có thể giảm số điểm này xuống còn 120 bằng cách đặt số đầu tiên if...vào kiểm tra có điều kiện for()tương tự như vậy: for(;($j=read-host)-cne"BYE"){if($j-ceq$j.ToUpper()){...Ngoài ra, thông số kỹ thuật nói 1930-1950.
Chính tả

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

Dễ đọc hơn:

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

Ah đã bỏ lỡ một vài cái đơn giản trong tôi, và mắc một số lỗi ngớ ngẩn. Nice +1
Kyle Rozendo

3

Befunge - 27x6 = 162 ký tự

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

EDIT: Hoàn toàn bỏ lỡ phần "BYE". Sắp có phiên bản mới.

EDIT 2: Thật ra, điều đó làm cho nó quá phức tạp đối với các kỹ năng Befunge ít ỏi của tôi. Tôi có thể thử lại sau, nhưng tôi không thể nghĩ ra bất kỳ cách đơn giản nào để thực hiện nó vào lúc này.


3

C # - 194 PHÍ

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

Với khoảng trắng:

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

Với một số cảm hứng từ Nellius và fR0DDY.

Xin vui lòng cho tôi biết nếu nó có thể được cải thiện.


Ngắn, nhưng FWIW, tôi nghĩ rằng rò rỉ này (gọi đệ quy Main()). Ngoài ra, tôi nghĩ rằng bạn muốn parens trong ?:biểu thức để có được !cả hai. Tôi đã thêm một câu trả lời với điều này và EOL (nhưng vẫn bị rò rỉ).
bw

tôi thấy bạn đã thêm parens và xóa bình luận của bạn. Làm tốt lắm. Bây giờ chỉnh sửa của tôi để thêm ảnh chụp màn hình vào câu trả lời của tôi có và không có parens là tranh luận. (Nhưng, vẫn bị rò rỉ) :-)
bw

@bill Vâng, ban đầu tôi đã làm hỏng bài kiểm tra của mình. Phiên bản không bị rò rỉ sẽ là 199 ký tự, chờ quá lâu :)
Richard

ha. Tôi thích Main();giải pháp ... không một người tỉnh táo nào sử dụng chương trình này đủ lâu để nó trở thành một vấn đề.
bw

Như Phoshi đã nói trong bình luận cho fR0DDY. Chương trình gặp sự cố khi bà ngủ thiếp đi.
Richard

3

D: 246 Nhân vật

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

Dễ đọc hơn:

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

javascript, 142 ký tự, 29 trong số đó thực hiện năm ngẫu nhiên

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

Awk: 97 ký tự

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

3

Windows PowerShell, 121 117

Do tính chất của nhiệm vụ, nó trông khá giống với giải pháp của Ty Auvil , mặc dù nó được viết độc lập:

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

Cảm ơn SpellingD đã gợi ý,


Tôi thích kết hợp regex của bạn, nhưng câu lệnh chuyển đổi là cồng kềnh. Cùng với gợi ý tôi đã đưa cho Ty, bạn có thể giảm số lượng nhân vật của mình xuống 117 bằng cách sử dụng regex với ifthay vì như thế này: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

Điều kỳ lạ là, mã Haskell thường ngắn hơn rất nhiều so với mã C so sánh khi viết chương trình 'nghiêm túc'.


Bạn có thể tránh nhập Charbằng cách sử dụng any(`elem`['a'..'z'])sđể kiểm tra các chữ cái viết thường.
hammar

2

APL (76)

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

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

Ngôn ngữ dài dòng chết tiệt ... :-)


1
Bạn có thể gọi lớp chỉ P. Và điều này không phát hiện đúng chữ hoa. Tôi có thể hét vào nó và nó vẫn không thể nghe thấy tôi. Bạn có thể rút ngắn phương thức chính để while(t(Console.ReadLine()));. Bạn có thể sử dụng using C=System.Console;khi bắt đầu để rút ngắn quyền truy cập ReadLine()WriteLine()đến C.ReadLine()C.WriteLine().
Joey

@Joey - Cảm ơn lời khuyên!
Kyle Rozendo

1

C # - 196 ký tự (nhưng bị rò rỉ)

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

Đó là câu trả lời của @ Richard (bị rò rỉ) với hai parens (xem bên dưới) và một \ n được thêm vào đó để lấy EOL trong cả hai trường hợp. Nếu không thì " + "chỉ là lãng phí không gian.

Định dạng

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

CẬP NHẬT: để làm rõ nhận xét của tôi về các parens đang cần, đây là những gì tôi nhận được mà không cần parens (tức là với giải pháp ban đầu của @ Richard):

không có parens

Và với các parens:

với parens

Không ai trong số này sử dụng bổ sung của tôi \nmặc dù.


Chỉ có 195 ở đây. Bạn đã đếm một ngắt dòng không cần thiết ở cuối?
Joey

1

Bash: 136 128 ký tự

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

Giới hạn thay thế: 132 123 ký tự

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

Bạn có thể nói chuyện với một người điếc vô hạn, nhưng cuộc trò chuyện với mã sau này bị giới hạn bởi ngăn xếp cuộc gọi. (Trong thử nghiệm của tôi, nó bị chấm dứt sau 4989 cuộc gọi.)


1

Javascript - 133 131 130 128 127 121 ký tự

phiên bản golf của giải pháp 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)+'!');

Chỉnh sửa: Đã lưu sáu ký tự khác với mẹo tuyệt vời này


Viết toán tử ternary như g=/[a-z]/.test(i)?'Huh?!...':'No...'và bạn phụ tùng 2 ký tự.
manatwork

Đã chỉnh sửa, cảm ơn cho con trỏ.
mật mã

1
Tôi tìm thấy thêm 1 ký tự: Math.ceil()ngắn hơn Math.floor(). Chỉ cần thay đổi năm cơ sở để giữ cho khoảng thời gian không thay đổi : Math.ceil(Math.random()*21+1929).
manatwork

Tuyệt vời, +1! Tôi đã lưu hai ký tự khác bằng cách thay đổi thời gian thành vòng lặp for.
codeporn

0

Clojure - 160 154 Nhân vật

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

Làm việc trên sân golf nhiều hơn một chút. Gợi ý chào mừng.

Chạy qua REPL


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

sử dụng

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
'
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.