Chris Pines "Gehörlose Oma"

22

Ich bin ein Mentor bei RubyLearning und eine der Übungen, die wir unseren Schülern geben, ist die "Deaf Grandma" -Übung aus Chris Pines Buch " Learn to Program ". Hier ist die Beschreibung:

Schreiben Sie ein Programm für gehörlose Großmütter. Was auch immer Sie zu Oma sagen (was auch immer Sie eingeben), sie sollte antworten mit: "Huh ?! Sprechen Sie, Junge!", Es sei denn, Sie rufen es (geben Sie alle Großbuchstaben ein). Wenn Sie schreien, kann sie Sie hören (oder glaubt es zumindest) und schreit zurück: "Nein, nicht seit 1938!"

Lassen Sie die Oma jedes Mal ein anderes Jahr rufen, damit Ihr Programm wirklich glaubwürdig wird. Vielleicht jedes beliebige Jahr zwischen 1930 und 1950. (Dieser Teil ist optional und wäre viel einfacher, wenn Sie den Abschnitt über Rubys Zufallszahlengenerator am Ende des Kapitels über Methoden lesen.) Sie können nicht aufhören, mit Oma zu sprechen, bis Sie Ruf "Tschüss".

Nach mehreren Kursiterationen habe ich versucht zu sehen, wie klein ich das bekommen kann und habe es jetzt auf 112 Zeichen reduziert:

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

Ich bin gespannt, in wie wenigen Zeichen dies in der Sprache Ihrer Wahl erreicht werden kann, da Ruby hier meiner Meinung nach bereits sehr gut abschneidet.

Bearbeiten: Die unten veröffentlichte Perl-Lösung führte zu

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

Das sind 92 Zeichen für den Ausdruck + 2 weitere Zeichen für die Optionen nund l.

Michael Kohl
quelle
In einem Golfkontext erfordert dies eine zusätzliche Spezifikation. Was soll passieren, wenn nach BYE eine zusätzliche Ausgabe erfolgt?
JB
Nur "BYE" beendet das Programm genau.
Michael Kohl

Antworten:

13

Perl, 85-91

Ausführen mit perl -nE '<code goes there>'( ngezählt in Programmgröße):

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

Das nachstehende Ausrufezeichen ist sehr teuer ...

Von IK vorgeschlagene Änderungen:

  • Die Verwendung eines regulären Ausdrucks anstelle einer Zeichenfolgenübereinstimmung erspart die -lglobale Option sowie zwei Programmzeichen: -3.
  • Verwenden einer tatsächlichen Variablen zum Speichern eines Werts und zum späteren Interpolieren (Genius! Wer hätte daran gedacht, eine Variable dafür zu verwenden?): 0.
  • Diese Variable $=als Ganzzahl festlegen: -4.

(Und es summiert sich immer noch nicht und ich bin zu müde, um herauszufinden, warum. Na ja, die letzte Zählung stimmt zumindest)

JB
quelle
Missbrauch $=und Verwendung eines regulären Ausdrucks für "BYE" führt zu 84 + 1:perl -nE '$==1930+rand 21;say/^BYE$/?last:uc eq$_?"NO, NOT SINCE $=!":"HUH?! SPEAK UP, SONNY!"'
Ilmari Karonen
@IlmariKaronen Integriert, danke!
JB
6

Python 120 Zeichen

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

Irgendwelche Tipps zur Verbesserung?

fR0DDY
quelle
Sie brauchen die Klammern um diese if-Anweisung nicht, auch ich bin mir ziemlich sicher, dass Python eine Rekursionsgrenze hat - aber das könnte einfach simulieren, dass Ihre Oma einschläft.
Phoshi
Oh! Ich habe vergessen, die Klammern zu entfernen. Danke :)
fR0DDY
Sie können einige Zeichen speichern, wenn Sie die erste Zeile entfernen, die zweite durch ersetzen s='', Ihre Anweisungen in der while-Schleife neu anordnen und die gesamte while-Schleife in eine Zeile einfügen : gist.github.com/3787809 Wenn Sie wirklich entschlossen wären , könnten Sie dies Speichern Sie 2 Zeichen mit Python 3 (raw_input () -> input (), aber print -> print ())
Matt
4

131 Zeichen in 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!"}}

Mit Leerzeichen:

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 Charaktere auf Joeys Vorschlag gedrückt.

Übrigens, 'Learn to Program' war das erste Programmierbuch, das ich jemals von vorne bis hinten gelesen habe.

Ty Auvil
quelle
Vielleicht möchten Sie einen Blick darauf werfen: codegolf.stackexchange.com/questions/191/…
Joey
Sie können dies auf 120 herabsetzen, indem Sie den ersten if...in die bedingte Prüfung von for()ähnlichem so zerquetschen : for(;($j=read-host)-cne"BYE"){if($j-ceq$j.ToUpper()){...Auch die Spezifikation sagt 1930-1950.
Rechtschreibung
3

C # - 234 Zeichen

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

Besser lesbar:

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
quelle
Ich habe ein paar einfache übersehen und ein paar dumme Fehler gemacht. Nice +1
Kyle Rozendo
3

Befunge - 27x6 = 162 Zeichen

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

EDIT: Den "BYE" Teil komplett verpasst. Neue Version kommt bald.

EDIT 2: Eigentlich macht das es ein bisschen zu komplex für meine mageren Befunge-Fähigkeiten. Vielleicht versuche ich es später noch einmal, aber ich kann mir im Moment keine einfache Art der Implementierung vorstellen.

Nemo157
quelle
3

C # - 194 Zeichen

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

Mit Leerzeichen:

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

Mit etwas Inspiration von Nellius und fR0DDY.

Bitte lassen Sie mich wissen, ob es verbessert werden kann.

Richard
quelle
Kurz, aber FWIW, ich denke, das ist undicht (rekursiver Aufruf Main()). Außerdem denke ich, dass Sie möchten, dass Parens im ?:Ausdruck das !in beiden bekommen. Ich habe eine Antwort mit diesem und EOL hinzugefügt (aber immer noch undicht).
bw
Ich sehe, Sie haben die Parens hinzugefügt und Ihren Kommentar entfernt. Gut gemacht. Jetzt ist meine Bearbeitung, um Screenshots zu meiner Antwort von mit und ohne die Eltern hinzuzufügen, umstritten. (Aber immer noch undicht) :-)
bw
@bill Ja, ich habe meine Tests anfangs durcheinander gebracht. Die nicht undichte Version wäre 199 Zeichen, waaay zu lang :)
Richard
Ha. Ich mag die Main();Lösung ... kein vernünftiger Mensch würde dieses Programm lange genug verwenden, um ein Problem darzustellen.
bw
Wie Phoshi im Kommentar zu fR0DDY sagte. Das Programm stürzt ab, wenn Oma einschläft.
Richard
3

D: 246 Zeichen

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

Mehr leserlich:

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
quelle
3

Javascript, 142 Zeichen, davon 29 zufällige Jahr

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
quelle
3

Awk: 97 Zeichen

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

Windows PowerShell, 121 117

Aufgrund der Art der Aufgabe sieht dies ziemlich identisch mit der Lösung von Ty Auvil aus , obwohl es unabhängig geschrieben wurde:

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

Vielen Dank an SpellingD für den Vorschlag,

Joey
quelle
Ich mag Ihre Regex-Übereinstimmung, aber die switch-Anweisung ist sehr sperrig. Zusammen mit dem Vorschlag, den ich Ty gemacht habe, können Sie die Anzahl Ihrer Charaktere auf 117 reduzieren, indem Sie Regex mit folgendem ifverwenden: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

Das Seltsame ist, dass Haskell-Code in der Regel viel kürzer ist als vergleichbarer C-Code, wenn man ein „ernstes“ Programm schreibt.

Marinus
quelle
Sie können den Import vermeiden, Charindem Sie any(`elem`['a'..'z'])szum Testen auf Kleinbuchstaben verwenden.
Hammar
2

APL (76)

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

C # - 345 Zeichen

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

Verdammt wortreiche Sprache ... :-)

Kyle Rozendo
quelle
1
Sie können die Klasse einfach anrufen P. Und dies erkennt Großbuchstaben nicht richtig. Ich kann es anschreien und es kann mich immer noch nicht hören. Sie können die Hauptmethode auf kürzen while(t(Console.ReadLine()));. Sie können using C=System.Console;zu Beginn verwenden, um den Zugriff auf ReadLine()und WriteLine()zu C.ReadLine()und zu verkürzen C.WriteLine().
Joey
@ Joey - Danke für die Tipps!
Kyle Rozendo
1

196 Zeichen (aber undicht)

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

Das ist @ Richards (undichte) Antwort mit zwei Parens (siehe unten) und einem \ n, das dort hinzugefügt wird, um die EOL in beiden Fällen zu erhalten. Ansonsten " + "ist das nur Platzverschwendung.

Formatiert

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: Um meinen Kommentar zu den benötigten Parens zu verdeutlichen, bekomme ich Folgendes ohne die Parens (dh mit @ Richards ursprünglicher Lösung):

ohne parens

Und mit den Eltern:

mit parens

Keiner von diesen nutzt meine zusätzliche \nobwohl.

bw
quelle
Es ist nur 195 hier. Haben Sie am Ende einen unnötigen Zeilenumbruch gezählt?
Joey
1

Bash: 136 128 Zeichen

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

Begrenzte Alternative: 132 123 Zeichen

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

Sie können unbegrenzt mit einem Gehörlosen sprechen, aber die Konversation mit diesem späteren Code wird durch die Anrufliste begrenzt. (In meinem Test wird es nach 4989 Aufrufen beendet.)

Mann bei der Arbeit
quelle
1

Javascript - 133 131 130 128 127 121 Zeichen

Golf-Version von www0z0ks Lösung

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

Bearbeiten: Mit diesem tollen Tipp wurden weitere sechs Zeichen gespeichert

codeporn
quelle
Schreiben Sie den ternären Operator als g=/[a-z]/.test(i)?'Huh?!...':'No...'und Sie sparen 2 Zeichen.
Manatwork
Bearbeitet, danke für den Hinweis.
Codeporn
1
1 weiteres Zeichen, das ich gefunden habe: Math.ceil()ist kürzer als Math.floor(). Ändern Sie einfach das Basisjahr das Intervall unverändert zu halten: Math.ceil(Math.random()*21+1929).
Manatwork
Großartig, +1! Ich habe zwei weitere Zeichen gespart, indem ich das while in eine for-Schleife geändert habe.
Codeporn
0

Clojure - 160 154 Zeichen

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

Ich arbeite ein bisschen mehr daran, Golf zu spielen. Vorschläge sind willkommen.

Führen Sie REPL durch

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

Verwendung

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
quelle