Кріс Пайн "Глуха бабуся"


22

Я наставник у RubyLearning, і однією з вправ, яку ми надаємо нашим студентам, є вправа "Глуха бабуся" з книги Кріса Пайна " Навчись програмувати ". Ось опис:

Напишіть програму глухих бабусь. Що б ви не сказали бабусі (що б ви не набрали), вона повинна відповісти: "Ага ?! Говоріть, синку!", Якщо ви не кричите це (введіть усі столиці). Якщо ви кричите, вона може почути вас (або, принаймні, вона так вважає) і кричить назад: "Ні, не з 1938 року!"

Щоб ваша програма була справді правдоподібною, попросіть бабусю кричати різний рік; можливо будь-який рік випадково між 1930 і 1950 роками. (Ця частина необов’язкова, і це було б набагато простіше, якби ви прочитали розділ про генератор випадкових чисел Рубі в кінці розділу про методи.) Ви не можете перестати спілкуватися з бабусею, поки не кричати "БАЙ".

Після декількох ітерацій курсу я спробував побачити, наскільки я маю змогу це отримати, і тепер зменшити його до 112 символів:

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

Мені цікаво побачити, як мало символів можна досягти мовою на ваш вибір, тому що я думаю, що Рубі вже тут справді добре.

Редагувати: Розміщене нижче рішення Perl призвело до

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

що становить 92 символи для виразу + 2 більше для параметрів nта та lпараметрів.


У контексті гольфу для цього потрібні додаткові умови. Що повинно відбутися, якщо є додаткові результати минулого BYE?
JB

Тільки "BYE" точно припиняє програму.
Майкл Коль

Відповіді:


13

Перл, 85 91

Запустити з perl -nE '<code goes there>'( nрахується в розмірі програми):

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

Цей знак оклику дуже дорогий ...

Зміни, запропоновані IK:

  • Використання регулярного вираження замість відповідності рядків позбавляє -lглобальний параметр, а також два символи програми: -3.
  • Використання фактичної змінної для збереження значення та використання його пізніше для інтерполяції (Genius! Хто б міг подумати про використання змінної для цього?): 0.
  • Зробити цю змінну $=, обмеженою цілим числом: -4.

(і це все ще не додається, і я занадто сонний, щоб дізнатися, чому. О, добре, остаточне підрахунок є принаймні правильним)


Зловживання $=та використання regexp для "BYE" зменшує це до 84 + 1:perl -nE '$==1930+rand 21;say/^BYE$/?last:uc eq$_?"NO, NOT SINCE $=!":"HUH?! SPEAK UP, SONNY!"'
Ilmari Karonen

@IlmariKaronen інтегрований, дякую!
JB

6

Пітон 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()

Будь-які підказки покращити?


Вам не потрібні дужки навколо цього, якщо твердження, також я впевнений, що у пітона є стеля рекурсії - але це може просто імітувати вашу бабусю, що засинає.
Phoshi

Ой! Я забув зняти дужки. Дякую :)
fR0DDY

Ви можете зберегти деякі символи, якщо ви вилучите перший рядок, заміните другий s='', перестановіть ваші висловлювання у циклі while і покладете цілий цикл while на один рядок: gist.github.com/3787809 Якщо ви дійсно визначились, ви могли б збережіть 2 символи, використовуючи python 3 (raw_input () -> input (), але надрукуйте -> print ())
Matt

4

131 символ у 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 / пробіл:

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 персонажів із пропозиції Джої.

BTW, «Навчися програмувати» була першою книгою програмування, яку я читав, обкладинку якої висвітлював.


Ви можете подивитися тут: codegolf.stackexchange.com/questions/191/…
Joey

Ви можете це знизити до 120, натиснувши першу if...в умовну перевірку for()подібного: так for(;($j=read-host)-cne"BYE"){if($j-ceq$j.ToUpper()){..., специфікація каже 1930-1950.
ПравописD

3

C # - 234 символів

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

Більш зрозумілі:

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

Ах пропустив кілька простих у моєму, і зробив кілька дурних помилок. Ніцца +1
Кайл Розендо

3

Befunge - 27x6 = 162 символи

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

EDIT: Повністю пропущено частину "BYE". Незабаром вийде нова версія.

EDIT 2: Насправді, це робить його занадто складним для моїх мізерних навичок Befunge. Я можу спробувати ще раз пізніше, але наразі не можу придумати жодного простого способу її реалізації.


3

C # - 194 ЧАРТІВ

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

З пробілами:

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

З деяким натхненням від Nellius та fR0DDY.

Будь ласка, дайте мені знати, чи можна її покращити.


Короткий, але FWIW, я думаю, це протікає (рекурсивно викликає Main()). Крім того, я думаю, ви хочете, щоб parenns у ?:виразі отримував !обоє. Я додав відповідь на це і EOL (але все ще протікає).
bw

я бачу, ви додали паролі та видалили ваш коментар. Хороша робота. Тепер моє редагування для додавання скріншотів до моєї відповіді з і без паронів суперечить. (Але, все ще витік) :-)
bw

@bill Так, я тестував свою перевірку спочатку. Версія, яка не протікає, складе 199 символів, занадто довга черга :)
Річард

га. Мені подобається Main();рішення ... жодна розумна людина не використовує цю програму досить довго, щоб вона була проблемою.
bw

Як сказав Фоші в коментарі до fR0DDY. Програма виходить з ладу, коли бабуся засинає.
Річард

3

Д: 246 персонажів

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

Більш розбірливо:

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 символи, 29 з них виконують випадковий рік

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

Windows PowerShell, 121 117

Зважаючи на характер завдання, це виглядає майже ідентично рішенню Тай Овіля , хоча воно було написане самостійно:

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

Завдяки SpellingD за пропозицію,


Мені подобається ваша відповідність регулярних виразів, але заява перемикання є об'ємною. Поряд із пропозицією, яку я дав Тай, ви можете зменшити кількість персонажів до 117, скориставшись регулярними символами ifзамість цього:for(;($j=read-host)-cne'BYE'){if($j-cmatch'[a-z]'){'Huh?! Speak up, sonny!'}else{"No, not since 19$(30..50|random)"}}
ПравописD

2

Хаскелл (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

Дивна річ у тому, що код Haskell, як правило, набагато коротший, ніж порівняний код C при написанні «серйозної» програми.


Ви можете уникнути імпорту Char, використовуючи any(`elem`['a'..'z'])sдля тестування малих літер.
хаммар


1

C # - 345 символів

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

Чорт багатослівної мови ... :-)


1
Ви можете просто зателефонувати в клас P. І це не правильно визначає великі регістри. Я можу на це кричати, і він все ще не чує мене. Можна скоротити основний метод до while(t(Console.ReadLine()));. Ви можете використовувати using C=System.Console;на початку , щоб скоротити доступ до ReadLine()і WriteLine()до C.ReadLine()і C.WriteLine().
Джої

@Joey - Дякую за поради!
Кайл Розендо

1

C # - 196 символів (але нещільних)

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

Це відповідь Річарда (нещільна) з двома паролями (див. Нижче) та \ n, доданими туди, щоб отримати EOL в обох випадках. Інакше " + "просто витрачений простір.

Відформатовано

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

ОНОВЛЕННЯ: щоб уточнити мій коментар щодо необхідності паронів, ось що я отримую без парен (тобто з оригінальним рішенням @ Річарда):

без парен

І з паронами:

з паренами

Жоден із них не використовує мого додаткового \n.


Тут лише 195 років. Ви порахували непотрібний розрив рядка наприкінці?
Джої

1

Bash: 136 128 символів

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

Обмежена альтернатива: 132 123 символів

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

Ви можете говорити з глухими нескінченно, але розмова з цим пізнішим кодом обмежена стеком дзвінків. (У моєму тесті він припиняється після 4989 дзвінків.)


1

Javascript - 133 131 130 128 127 121 символів

гольф-версія рішення 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)+'!');

Редагувати: Збережено ще шість символів за допомогою цієї чудової поради


Напишіть термінального оператора як g=/[a-z]/.test(i)?'Huh?!...':'No...'і запасите 2 символи.
манатура

Відредаговано, дякую за вказівник.
codeporn

1
Я знайшов ще 1 символу: Math.ceil()коротший за Math.floor(). Просто змініть базовий рік , щоб зберегти інтервал без змін: Math.ceil(Math.random()*21+1929).
манатура

Чудово, +1! Я врятував ще два символи, змінюючи час на цикл for.
codeporn

0

Clojure - 160 154 персонажів

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

Робота над гольфом трохи більше. Пропозиції вітаються.

Пробіг через 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!"]]}

використання

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
'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.