“Nonna sorda” di Chris Pine


22

Sono un mentore di RubyLearning e uno degli esercizi che facciamo ai nostri studenti è l'esercizio "Nonna sorda" dal libro " Impara al programma " di Chris Pine . Ecco la descrizione:

Scrivi un programma Nonna sorda. Qualunque cosa tu dica alla nonna (qualunque cosa tu digiti), lei dovrebbe rispondere con: "Eh ?! Parla, figliolo!", A meno che tu non lo gridi (digita tutte le maiuscole). Se gridi, ti sente (o almeno la pensa così) e grida: "No, non dal 1938!"

Per rendere il tuo programma davvero credibile, chiedi alla nonna di urlare un anno diverso ogni volta; forse ogni anno a caso tra il 1930 e il 1950. (Questa parte è facoltativa e sarebbe molto più semplice se leggi la sezione sul generatore di numeri casuali di Ruby alla fine del capitolo dei metodi.) Non puoi smettere di parlare con la nonna fino a quando gridare "BYE".

Dopo varie iterazioni di corsi ho provato a vedere quanto sono piccolo e ora riesco a ridurlo a 112 caratteri:

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

Sono curioso di vedere in quanti pochi personaggi questo può essere realizzato nella lingua che preferisci, perché penso che Ruby stia già andando molto bene qui.

Modifica: la soluzione Perl pubblicata di seguito ha portato a

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

che è di 92 caratteri per l'espressione + 2 in più per le opzioni ne l.


In un contesto di golf, ciò richiede ulteriori specifiche. Cosa dovrebbe succedere se c'è un output extra oltre il BYE?
JB

Solo "BYE" termina esattamente il programma.
Michael Kohl,

Risposte:


13

Perl, 85 91

Esegui con perl -nE '<code goes there>'( nconteggiato nella dimensione del programma):

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

Quel punto esclamativo finale è molto costoso ...

Modifiche suggerite da IK:

  • L'uso di una regexp invece di una corrispondenza di stringa risparmia l' -lopzione globale e due caratteri di programma: -3.
  • Usare una variabile reale per salvare un valore e usarlo in seguito per l'interpolazione (Genius! Chi avrebbe mai pensato di usare una variabile per quello?): 0.
  • Rendendo quella variabile $=, vincolata ad un numero intero: -4.

(e ancora non si somma e ho troppo sonno per scoprire perché. Oh beh, il conteggio finale è giusto almeno)


Abusare $=e usare una regexp per "BYE" arriva a 84 + 1:perl -nE '$==1930+rand 21;say/^BYE$/?last:uc eq$_?"NO, NOT SINCE $=!":"HUH?! SPEAK UP, SONNY!"'
Ilmari Karonen,

@IlmariKaronen integrato, grazie!
JB,

6

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

Qualche suggerimento per migliorare?


Non hai bisogno delle parentesi attorno a questa dichiarazione if, inoltre sono abbastanza sicuro che Python abbia un limite di ricorsione - ma questo potrebbe simulare che tua nonna si addormenti.
Phoshi,

Oh! Ho dimenticato di rimuovere le parentesi. Grazie :)
fR0DDY,

Puoi salvare alcuni caratteri se rimuovi la prima riga, sostituisci la seconda con s='', riordina le tue istruzioni nel tuo ciclo while e metti l'intero ciclo while su una riga: gist.github.com/3787809 Se fossi davvero determinato, potresti salva 2 caratteri usando python 3 (raw_input () -> input (), ma print -> print ())
Matt,

4

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

Con spazi bianchi:

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

Spremuto 18 personaggi dal suggerimento di Joey.

A proposito, "Impara a programmare" è stato il primo libro di programmazione che abbia mai letto da copertina a copertina.


Potresti dare un'occhiata qui: codegolf.stackexchange.com/questions/191/…
Joey,

Puoi farlo scendere a 120 schiacciando il primo if...nel controllo condizionale del for()simile così: for(;($j=read-host)-cne"BYE"){if($j-ceq$j.ToUpper()){...Inoltre, la specifica dice 1930-1950.
OrtografiaD

3

C # - 234 caratteri

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

Più leggibile:

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 ne ho perse alcune semplici e ho fatto alcuni sciocchi errori. Bello +1
Kyle Rozendo

3

Befunge - 27x6 = 162 caratteri

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

EDIT: completamente perso la parte "BYE". Nuova versione in arrivo.

EDIT 2: In realtà, questo lo rende un po 'troppo complesso per le mie magre abilità di Befunge. Potrei riprovare più tardi, ma al momento non riesco a pensare a un modo semplice per implementarlo.


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

Con spazi bianchi:

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

Con qualche ispirazione da Nellius e fR0DDY.

Per favore fatemi sapere se può essere migliorato.


Insomma, ma FWIW, penso che questo abbia delle perdite (chiamata ricorsiva Main()). Inoltre, penso che tu voglia le parentesi ?:nell'espressione per ottenere !entrambi. Ho aggiunto una risposta con questo e EOL (ma ancora perdite).
bw

vedo che hai aggiunto le parentesi e rimosso il tuo commento. Buon lavoro. Ora la mia modifica per aggiungere schermate alla mia risposta di con e senza le parentesi è controversa. (Ma, ancora che perde) :-)
bw

@bill Sì, inizialmente ho incasinato i miei test. La versione senza perdite sarebbe di 199 caratteri, forse troppo a lungo :)
Richard

ha. Mi piace la Main();soluzione ... nessuna persona sana di mente userebbe questo programma abbastanza a lungo da essere un problema.
bw

Come ha detto Phoshi nel commento a fR0DDY. Il programma si blocca quando la nonna si addormenta.
Richard,

3

D: 246 personaggi

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

Più leggibilmente:

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 caratteri, 29 di questi eseguono un anno casuale

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 caratteri

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

3

Windows PowerShell, 121 117

A causa della natura del compito questo sembra praticamente identico alla soluzione di Ty Auvil , sebbene sia stata scritta in modo indipendente:

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

Grazie a SpellingD per il suggerimento,


Mi piace la tua corrispondenza regex, ma l'istruzione switch è molto voluminosa. Insieme al suggerimento che ho dato a Ty, potresti ridurre il conteggio dei personaggi a 117 usando regex con un ifinvece come questo:for(;($j=read-host)-cne'BYE'){if($j-cmatch'[a-z]'){'Huh?! Speak up, sonny!'}else{"No, not since 19$(30..50|random)"}}
OrtografiaD

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

La cosa strana è che il codice Haskell è di solito molto più breve del codice C comparabile quando si scrive un programma "serio".


È possibile evitare l'importazione Charutilizzando any(`elem`['a'..'z'])sper verificare le lettere minuscole.
Hammar,

2

APL (76)

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

1

C # - 345 caratteri

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

Maledetto linguaggio verboso ... :-)


1
Puoi chiamare la lezione solo P. E questo non rileva correttamente le maiuscole. Posso urlare e ancora non riesco a sentirmi. È possibile abbreviare il metodo principale in while(t(Console.ReadLine()));. È possibile utilizzare using C=System.Console;all'inizio per abbreviare l'accesso a ReadLine()e WriteLine()verso C.ReadLine()e C.WriteLine().
Joey,

@Joey - Grazie per i suggerimenti!
Kyle Rozendo,

1

C # - 196 caratteri (ma con perdite)

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

Questa è la risposta (che perde) di Richard con due parentesi (vedi sotto) e un \ n aggiunto per ottenere l'EOL in entrambi i casi. Altrimenti " + "è solo uno spazio sprecato.

formattato

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

AGGIORNAMENTO: per chiarire il mio commento sulla necessità delle parentesi, ecco cosa ottengo senza le parentesi (cioè con la soluzione originale di @ Richard):

senza genitori

E con i genitori:

con i genitori

Nessuno di questi usa il mio ulteriore \nperò.


Sono solo 195 qui. Hai contato un'interruzione di riga non necessaria alla fine?
Joey,

1

Bash: 136 128 caratteri

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

Alternativa limitata: 132 123 caratteri

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

Puoi parlare con un sordo all'infinito, ma la conversazione con questo codice successivo è limitata dallo stack di chiamate. (Nel mio test viene terminato dopo 4989 chiamate.)


1

Javascript - 133 131 130 128 127 121 caratteri

versione golfata della soluzione 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)+'!');

Modifica: hai salvato altri sei caratteri con questo fantastico suggerimento


Scrivi l'operatore ternario come g=/[a-z]/.test(i)?'Huh?!...':'No...'e risparmi 2 caratteri.
arte

A cura, grazie per il puntatore.
codeporn,

1
Ho trovato un altro personaggio: Math.ceil()è più corto di Math.floor(). Basta cambiare l'anno di riferimento per mantenere inalterato l'intervallo: Math.ceil(Math.random()*21+1929).
arte

Ottimo, +1! Ho salvato altri due caratteri cambiando il tempo in un ciclo for.
codeporn,

0

Clojure - 160 154 personaggi

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

Lavorando sul golf un po 'di più. Suggerimenti benvenuti.

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

uso

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
'
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.