Update: Программа распечатывает известное стихотворение, я пытался сделать ее как можно короче, и пока не вижу как ее можно еще умять — хорошо бы дойти до 1000 символов — тогда кат был бы не обязателен.
#include <stdio.h>
int main(int s) {
switch (s) {
case 1:
printf("Вот дом,\n"); break;
case 2:
printf("\nА это пшеница,\n"); break;
case 3:
printf("\nА это весёлая птица-синица,\n"); break;
case 4:
printf("\nВот кот,\n"); break;
case 5:
printf("\nВот пёс без хвоста,\n"); break;
case 6:
printf("\nА это корова безрогая,\nЛягнувшая"); break;
case 7:
printf("\nА это старушка, седая и строгая,\n"); break;
case 8:
printf("\nА это ленивый и толстый пастух,\n");
}
switch (s) {
case 9:
printf("\nВот два петуха,\nКоторые будят того пастуха,\n");
case 8:
printf("Который бранится с коровницей строгою,\n");
case 7:
printf("Которая доит корову безрогую,\nЛягнувшую");
case 6:
printf(" старого пса без хвоста,\n");
case 5:
printf("Который за шиворот треплет кота,\n");
case 4:
printf("Который пугает и ловит синицу,\n");
case 3:
printf("Которая часто ворует пшеницу,\n");
case 2:
printf("Которая в темном чулане хранится\nВ доме,\n");
case 1:
printf("Который построил Джек.\n");
}
if (s++<9) main(s);
}
Комментарии (56)
Zalechi
05.04.2019 19:18+1Название музыкальной группы исполняющей песню «Джек» текст которой содержит слова применённые вами.
Извините, но я не программист и не понял, что Вы хотите сказать. Много лет на хабре, но такого не видал. Обычно авторы поясняют и разжёвывают.delphinpro
05.04.2019 19:21+2Программный вывод всем известного текста.
Прикольный код, зачем минуса-то летят? На статью не тянет?rekub Автор
05.04.2019 19:24-6наверно потому, что подзаголовок «сообщество разработчиков» уже не имеет никакого отношения к habr'у.
Zalechi
05.04.2019 20:18Ну вы не будьте столь категоричны. Взять меня к примеру — не разработчи, но связист и местный житель.
Как Вы воспримите статью с таким скромным содержанием:
Инспектируем трафик локалки и внешки
ip inspect name INSPECT_OUT dns
ip inspect name INSPECT_OUT icmp
ip inspect name INSPECT_OUT ntp
ip inspect name INSPECT_OUT tcp router-traffic
ip inspect name INSPECT_OUT udp router-traffic
ip inspect name INSPECT_OUT icmp router-trafficrekub Автор
05.04.2019 21:27Я последние 13 лет слишком далек от настроек цисок, так что оценить не смог бы.
vectorplus
05.04.2019 23:48Как Вы воспримите статью
Я бы промотал ленту и забыл, что такая статья существует.
Zalechi
06.04.2019 00:44Меня зацепило, то что код для программиста лёгкий, да и я сам его вроде читаю, но нетпонимаю полноценно, как работает. А описания никакого нет. Ну и полез задавать вопросы.
Zalechi
05.04.2019 20:03Ну раз такое дело, помогите понять…
1. Инициализация программы функцией main()
2. Switch() — не знаю что делает.
3. Case () — какое-то пред-удсловие, если так можно выразиться?
4. Printf () — выводит на экран.
5. Break — похоже на то что не даёт printf сделать свою работу сразу.
6. If () — в итоге я не понял условие и, что оно выполняет.
Вижу, что до 7го case-а включительно используется break, потом case-ы идут с 9го по убывающей и в конце программа ждёт исполнения условия с аргументом (s++<9) возвращает в main(s)?
Только как это в итоге выведет н экран я не понимаю. Знаю, что могу покопать интернет по каждой функции, но раз такая пляска было интересно почитать вашу интерпретацию кода.
Пишу с мобилы, извините за ошибки.rekub Автор
05.04.2019 21:46-1Ну, это еще целая статья будет, а меня так заминусовали, что вряд ли я смогу ее выложить ((
DocJester
06.04.2019 06:24Switch/case — это оператор множественного ветвления; сама программа представляет собой несложную рекурсию.
Neikist
05.04.2019 19:31+1Эм… Это несет какой то глубокий смысл? Или объясняет тонкости работы какого то механизма? Какую это практическую пользу несет?
rekub Автор
05.04.2019 19:35-6Just for fun.
жуть какая — прямо в Совок вернули — «Чему учит данное произведение?»
Но если очень хочется, то как учебный пример, для начинающего учить программирование, очень даже.Neikist
05.04.2019 20:15+1Имхо, это все же не уровень хабра. Я тут выбирал из тем «разобрать работу под капотом какого нибудь хитрого класса из android SDK», или «варианты архитектуры обменов приложения под андроид на kotlin с беком на 1с с описанием плюсов и минусов» и решил что они обе слишком простенькие, подожду еще писать пока что поинтереснее не придет в голову, а тут такое…
rekub Автор
05.04.2019 20:56А какое такое? Простое? А вы разобрали пример? Вы поняли почему эта программа распечатает весь текст стихотворения? Вы видели много сишных программ с рекурсией функции main? — все-таки раздел «ненормальное пронраммирование». И если хотите вызов, напишите программу, которая распечатает весь текст стихотворения, и при этом будет короче (можно на другом языке).
Neikist
05.04.2019 21:21+1В том и проблема что ничего хитрого не увидел и понял сразу, хотя на C не писал почти. P.S. Оно конечно прикольно да, второй switch оригинально сделан, в связке с рекурсией, но слишком как то все просто в итоге. Не говоря уж что в продакшен код я бы такой точно не выпустил. Он вроде простой, но с первого взгляда может не распознаться, соответственно возможно ошибку допустить.
rekub Автор
05.04.2019 21:32+1В продакшен был бы тупо выложен сам текст стихотворения, чего уж там.
Neikist
05.04.2019 21:37+2Мне кажется если бы вы именно в формате статьи для новичков в программировании пост написали с описанием как это работает — он бы зашел, но в таком виде непонятна его ЦА. Программистам с опытом квайны и такого рода головоломки, имхо, скучны уже, а новички без описания скорее всего не разберутся.
Zalechi
05.04.2019 23:11Я например — конечно догадался что она весь текст красиво выводит на экран, но как не понял. Думаю окей. Давай в комментах вместе с ребятами пофантазирую. Бестолку — заминусовали)
Neikist
05.04.2019 23:29В том и проблема. Человек знающий операторы применяемые быстро поймет что к чему, решение пусть местами элегантное, но простое. А без знаний операторов — вряд ли.
DocJester
06.04.2019 06:27Решение элегантное.
Но проблема в том, что выложить код не значит написать статью.
К тому же, если уж говорить о «Не нормальном программировании», то уровень статей Хабра — это не рекурсивный вызов main, а представление данной функции как массива.
Да, так можно.
Да, такое делали.
Нет, так делал не я, и нет, я написать такую статью не смогу.
SbWereWolf
05.04.2019 20:56+1Если голову включить над кодом, то забавно, програмка прокручивает себя 8 раз и прекращает работу.
За это время она успевает сгенерить стихотворение.
Но Хабр это посты в которых тебе разжёвывают от и до, а в конце ты такой «вау!» и просветлился, а эта заметка, это просто анекдот.
Надо было прикрутить подводку (интро) про авто-генерацию стихов что ли.
Даже не понятно зачем читатель на него время потратил.
Quiensabe
05.04.2019 22:17Уже забыл Си, но если задача сделать короче, то почему не нельзя как-то так (псевокод)
main (int s){
if (s=1) print("Вот дом,\n");
if (s=2) print("\nА это пшеница,\n");
if (s=3) print("\nА это весёлая птица-синица,\n");
if (s=4) print("\nВот кот,\n");
if (s=5) print("\nВот пёс без хвоста,\n");
if (s=6) print("\nА это корова безрогая,\nЛягнувшая");
if (s=7) print("\nА это старушка, седая и строгая,\n");
if (s=8) print("\nА это ленивый и толстый пастух,\n");
goto s;
9: print("\nВот два петуха,\nКоторые будят того пастуха,\n");
8: print("Который бранится с коровницей строгою,\n");
7: print("Которая доит корову безрогую,\nЛягнувшую");
6: print(" старого пса без хвоста,\n");
5: print("Который за шиворот треплет кота,\n");
4: print("Который пугает и ловит синицу,\n");
3: print("Которая часто ворует пшеницу,\n");
2: print("Которая в темном чулане хранится\nВ доме,\n");
1: print("Который построил Джек.\n");
if (s++<9) main(s);
}staticlab
05.04.2019 22:36Нельзя, потому что в C метки являются идентификаторами, т.е. нельзя сделать числовую метку и перейти на неё по значению переменной.
rekub Автор
05.04.2019 22:43так можно на бейсике, например, но там не пройдет номер с рекурсией и понадобится цикл, в итоге надо написать работающий пример, чтобы понять короче он или нет.
Quiensabe
05.04.2019 23:11+4Можно и без меток обойтисьfor(s=1;s<10;s++){ if (s=1) print("Вот дом,\n"); if (s=2) print("\nА это пшеница,\n"); if (s=3) print("\nА это весёлая птица-синица,\n"); if (s=4) print("\nВот кот,\n"); if (s=5) print("\nВот пёс без хвоста,\n"); if (s=6) print("\nА это корова безрогая,\nЛягнувшая"); if (s=7) print("\nА это старушка, седая и строгая,\n"); if (s=8) print("\nА это ленивый и толстый пастух,\n"); if (s>8) print("\nВот два петуха,\nКоторые будят того пастуха,\n"); if (s>7) print("Который бранится с коровницей строгою,\n"); if (s>6) print("Которая доит корову безрогую,\nЛягнувшую"); if (s>5) print(" старого пса без хвоста,\n"); if (s>4) print("Который за шиворот треплет кота,\n"); if (s>3) print("Который пугает и ловит синицу,\n"); if (s>2) print("Которая часто ворует пшеницу,\n"); if (s>1) print("Которая в темном чулане хранится\nВ доме,\n"); print("Который построил Джек.\n"); }
Quiensabe
06.04.2019 01:19+2#include <stdio.h> const char* a[] = {"Вот дом,\n","\nА это пшеница,\n","\nА это весёлая птица-синица,\n","\nВот кот,\n","\nВот пёс без хвоста,\n","\nА это корова безрогая,\nЛягнувшая","\nА это старушка, седая и строгая,\n","\nА это ленивый и толстый пастух,\n","","","\nВот два петуха,\nКоторые будят того пастуха,\n","Который бранится с коровницей строгою,\n","Которая доит корову безрогую,\nЛягнувшую"," старого пса без хвоста,\n","Который за шиворот треплет кота,\n","Который пугает и ловит синицу,\n","Которая часто ворует пшеницу,\n","Которая в темном чулане хранится\nВ доме,\n","Который построил Джек.\n"}; int main() { for(int s=1;s<9;s++) { printf(a[s-1]); for(int b=8;b>=0;b--) { if (s>b) printf(a[18-b]); }}}
Онлайн компилятор Сиrekub Автор
06.04.2019 01:27+1в первом for надо s<10, и в итоге суперский результат в 725 символов — уже близко к примеру с gzip!
Quiensabe
06.04.2019 13:23в первом for надо s<10,
По ссылке правильный вариант, а сюда скопировал с ошибкой :)
Сам код в этом случае190 сиволов#include <stdio.h>const char* a[]={"","","","","","","","","","","","","","","","","",""}; int main(){for(int s=1;s<10;s++){printf(a[s-1]);for(int b=8;b>=0;b--){if(s>b)printf(a[18-b]);}}}
oam2oam
06.04.2019 01:38+1ну что вы, конечно можно!
void * m[]={&&a,&&b}; goto *m[0]; a:; b:;
rekub Автор
06.04.2019 01:46это какие-то неправильные пчелы %)
oam2oam
06.04.2019 01:50в С можно вообще практически все…
Вот очевидное сокращение программ:
вместо int main() { int s можно писать main(s) { — переменная s будет по умолчанию целой… и да, два цикла можно, наверно, развернуть в что-то типа
const char* a[] = {... main(s,i){ return (s>9?0:i>0?printf("%s%s",a[i],a[10-i]),main(s,0):main(s,i+1)); }
ну или как-то так (что-то не думается :) — в этом случае рекурсия сильно сократит текст (жалко, что имя main не сократишь)
kirillsulim
05.04.2019 22:38Можно пожать полный текст в gzip и при вызове распаковывать. В питоне 3 уложился в 579 символов:
import zlib import base64 print(zlib.decompress(base64.a85decode('Gb"/%92<Ai%,LXl4ofQA-;c3)JtRu9>TuluFIKSY($ln0m)b$k@08h]Psptlp#l-6c_S55>%6KCCYiFGN*k)SB.iqk,B!!.P$$lAh/c$_b\\ujX]Kt`pab.SW9((V"Ya8S>NiI%F.</+e*:FJk2C(pe\\Ddpo,?\\]E--\'\\a,(%l"@J=>$3BN)UXoa+X?3>B\\YQ#TA/FeP-\'&#--U%i:f8UbZr<j#=BA#X.R5qg.B#nUjqJ\\Etb4bj!Obh]5!`+ullW,GcQFuE69b8C>o%g,tK\'mHTSL$=Q9dH$33E]>7STER$UQ;KFsMFWT=8daSY*\'(7XE(4shA]I""F!iiZV+*tW,X>B[$$L_3!KO(l68-Xk@dWVG(/7h$NatT?a"plK3Q_,MLTCi-^pPJ6"]08OR;Ef\\"[Xb0R]K:=l/ajog[H,&#lLnJFc^lPO2&:JrI6H3HM*h@qO`u0F9<..,W4S-"brQc-#VG*Mqa]R45PISL&')).decode())
Думаю, что в си можно сделать аналогично, хотя и будет чуть длиннее.
rekub Автор
05.04.2019 22:41Здорово, работает! жаль пропуски между многостишиями пропустили, но это не суть уже.
aknew
05.04.2019 23:15+1А макросы подойдут? Если да, то можно сделать вот так:
#define p printf #define c case #define b break;
и заменить все вхождения case, printf и break;. Это сэкономит 155 символов и в сумме вроде получается меньше 1000rekub Автор
06.04.2019 01:41да если это додумать то этот вариант занимает 844 символа и почетное третье место после gzip'а и строк в массиве:
#include <stdio.h> #define c(L,S) case L:printf(S); #define b break; int main(int s) { switch (s) { c(1,"Вот дом,\n")b c(2,"\nА это пшеница,\n")b c(3,"\nА это весёлая птица-синица,\n")b c(4,"\nВот кот,\n")b c(5,"\nВот пёс без хвоста,\n")b c(6,"\nА это корова безрогая,\nЛягнувшая")b c(7,"\nА это старушка, седая и строгая,\n")b c(8,"\nА это ленивый и толстый пастух,\n") } switch (s) { c(9,"\nВот два петуха,\nКоторые будят того пастуха,\n") c(8,"Который бранится с коровницей строгою,\n") c(7,"Которая доит корову безрогую,\nЛягнувшую") c(6," старого пса без хвоста,\n") c(5,"Который за шиворот треплет кота,\n") c(4,"Который пугает и ловит синицу,\n") c(3,"Которая часто ворует пшеницу,\n") c(2,"Которая в темном чулане хранится\nВ доме,\n") c(1,"Который построил Джек.\n") } if (s++<9) main(s); }
Griboks
05.04.2019 23:21+1Что это за ерунда? Можно как-нибудь добавить подобные статьи в черный список?
third112
05.04.2019 23:43+1А меня, как говорят в соцсетях: «улыбнуло» :) Пусть на пару минут — ну так и в серьезных журналах бывает веселая картинка без особых претензий. Спасибо.
Автор правильно указал хаб: «Ненормальное программирование», а вот хаб «Программирование» лучше убрать, чтобы не было завышенных ожиданий у читателей, м.б. добавить «Кодобред». ИМХО тогда никаких претензий быть не должно, тем более, что заметка породила содержательные комменты с вариантами решений: нпр.
staticlab
05.04.2019 23:49+3#include <stdio.h> const char *SUBJECT[] = { "house that Jack built.", "malt", "rat,", "cat,", "dog,", "cow with the crumpled horn,", "maiden all forlorn,", "man all tatter'd and torn,", "priest all shaven and shorn,", "cock that crow'd in the morn,", "farmer sowing his corn," }; const char *STATE[] = { "lay in", "ate", "kill'd", "worried", "toss'd", "milk'd", "kiss'd", "married", "waked", "kept" }; int main() { for (int i = 0; i < 11; i++) { printf("\nThis is "); for (int j = i; j >= 0; j--) { printf("the %s\n", SUBJECT[j]); if (j) printf("That %s ", STATE[j-1]); } } }
$ wc -c jack.c 650
Sirion
06.04.2019 01:00+2Проблема не в том, что плохой код, а в том, что плохая статья. Не тот формат. Для публикации кусков кода без пояснений существуют другие ресурсы. Посмотрите аналогичные статьи в хабе «Ненормальное программирование», сравните, что есть в них и чего нет у вас.
kvaps
06.04.2019 02:29+2#!/bin/bash A=( "Вот дом,\n" "\nА это пшеница,\n" "\nА это весёлая птица-синица,\n" "\nВот кот,\n" "\nВот пёс без хвоста,\n" "\nА это корова безрогая,\nЛягнувшая" "\nА это старушка, седая и строгая,\n" "\nА это ленивый и толстый пастух,\n" ) B=( "\nВот два петуха,\nКоторые будят того пастуха,\n" "Который бранится с коровницей строгою,\n" "Которая доит корову безрогую,\nЛягнувшую" " старого пса без хвоста,\n" "Который за шиворот треплет кота,\n" "Который пугает и ловит синицу,\n" "Которая часто ворует пшеницу,\n" "Которая в темном чулане хранится\nВ доме,\n" "Который построил Джек.\n" ) for ((i=0; i<=9; i++)); do printf "$(printf "%s" "${A[$i]}" "${B[@]: -$(($i+1))}")" done
GrigorGri
06.04.2019 03:52В почти всех решениях можно заменить "\nА это " на s+"...", что даст выгоду в 6*5=30 символов (-декларация s). Тоже самое с "Котор"
pakager
06.04.2019 05:02#include <stdio.h> #define A ,"\nА это " #define K ,"\nКотор" char* a[]={"\nВот два петуха,"A"ленивый и толстый пастух,"A"старушка, седая и строгая,"A"корова безрогая,\nЛягнувшая","\nВот пёс без хвоста,","\nВот кот,"A"весёлая птица-синица,"A"пшеница,","Вот дом,"K"ые будят того пастуха,"K"ый бранится с коровницей строгою,"K"ая доит корову безрогую,\nЛягнувшую"," старого пса без хвоста,"K"ый за шиворот треплет кота,"K"ый пугает и ловит синицу,"K"ая часто ворует пшеницу,"K"ая в темном чулане хранится\nВ доме,"K"ый построил Джек.\n"}; main(){int x,y;for(x=8;x>=0;x--){printf(a[x]);for(y=x;y<9;y++){printf(a[y+9]);};};}
$ wc -m jack.c 621 jack.c
netricks
06.04.2019 05:14Поставил минус. Думаю, поставил правильно.
Свитч-кейс автомат — это может быть интересно. Рекурсивный main — это может быть интересно. Кстати, по стандарту языка нельзя рекурсивный main.
Но статья требует какого-то рассмотрения чтоли… А иначе общий уровень хабра будет неуклонно падать и получим со временем ithappens...
third112
06.04.2019 07:26Но статья требует какого-то рассмотрения чтоли…
Интересный вопрос. А конкретнее можно: какое тут нужно рассмотрение? — Пересказ вики-статьи о рекурсии явно не нужен. Объяснение для чайника как это работает? — Пусть запустит в отладке и посмотрит по шагам, если в уме сообразить не может.
По первому впечатлению и мне показалось, что заметка неприлично краткая. Но подумал: как бы я это написал? — И понял, что однозначного ответа пока не имею. М.б. Вы поможете? (Вопрос не праздный: надеюсь понятно, что это мне нужно для публикаций на другие темы).
Заранее спасибо.rekub Автор
06.04.2019 09:05-1Лично для меня habr куда-то скатился, и стал чудовищно скучен — «Хабр уже не торт», именно из-за того, что наличие в статье чего-то раздражающего немедленно тянет ее в бан. К сожалению, некий вызов на подумать, тоже крайне раздражает, вот что грустно… Неразмусолил код, который выложил, — читатель должен сам думать — в бан. Высказался резко — в бан, например одну прошлую мою статью мою забанили за фразу «это не программист, а дурак какой-то». Это совет как сделать, чтобы не забанили. Для меня, как для автора, это слишком серьёзные ограничения, так что моих статей здесь, видимо, больше не будет ((
third112
06.04.2019 09:25На текущий момент из 1700 читателей только ок. 3% оставили комменты и оценки. Комменты есть интересные, а 3% оценок не могут отразить общего мнения. Как и во многих других статьях. ИМХО если бы не возникали ограничения, то на рейтинг никто бы не смотрел, а писали бы ради обратной связи.
rekub Автор
06.04.2019 09:00+1не видел на ithappens кусков кода. Может бывает, конечно, я их мало смотрел.
Zalechi
ТТ 34
rekub Автор
Непонятно, что вы хотите сказать?
zagayevskiy
Такой же вопрос и к вам.
rekub Автор
Текст программы вполне самодокументируемый и интересный. Добавил небольшой комментарий.
thatsme
Это отличная пятничная шутка для программистов. Да она простая. Но вполне себе прикольная. Само стихотворение рекурсивное, и просто просится в код. Я думаю шутка удалась. Однако автору сочуствую.