“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.