Puzzle 代码:自动机
我用这些规则创造了终极的笑声发生器。你能用你最喜欢的语言巧妙地实现它吗 规则: 在每次迭代中,都会发生以下转换Puzzle 代码:自动机,puzzle,code-golf,rosetta-stone,automata,Puzzle,Code Golf,Rosetta Stone,Automata,我用这些规则创造了终极的笑声发生器。你能用你最喜欢的语言巧妙地实现它吗 规则: 在每次迭代中,都会发生以下转换 H -> AH A -> HA AA -> HA HH -> AH AAH -> HA HAA -> AH 这是一个非常简单的C++版本: #include <iostream> #include <sstream> using namespace std; #define LINES 10 #define
H -> AH
A -> HA
AA -> HA
HH -> AH
AAH -> HA
HAA -> AH
这是一个非常简单的C++版本:
#include <iostream>
#include <sstream>
using namespace std;
#define LINES 10
#define put(t) s << t; cout << t
#define r1(o,a,c0) \
if(c[0]==c0) {put(o); s.unget(); s.unget(); a; continue;}
#define r2(o,a,c0,c1) \
if(c[0]==c0 && c[1]==c1) {put(o); s.unget(); a; continue;}
#define r3(o,a,c0,c1,c2) \
if(c[0]==c0 && c[1]==c1 && c[2]==c2) {put(o); a; continue;}
int main() {
char c[3];
stringstream s;
put("H\n\n");
for(int i=2;i<LINES*2;) {
s.read(c,3);
r3("AH",,'H','A','A');
r3("HA",,'A','A','H');
r2("AH",,'H','H');
r2("HA",,'A','A');
r1("HA",,'A');
r1("AH",,'H');
r1("\n",i++,'\n');
}
}
Haskell的简单翻译:
grammar = iterate step
where
step ('H':'A':'A':xs) = 'A':'H':step xs
step ('A':'A':'H':xs) = 'H':'A':step xs
step ('A':'A':xs) = 'H':'A':step xs
step ('H':'H':xs) = 'A':'H':step xs
step ('H':xs) = 'A':'H':step xs
step ('A':xs) = 'H':'A':step xs
step [] = []
以及一个较短的版本(122个字符,优化为三个派生规则+基本情况):
和C++的转换(182字符,只需一次迭代,在命令行中调用初始状态):
#包括
#定义putchar
int main(int,char**v){char*p=v[1];while(*p){p[1]==65&&~*p&p[2]?o(p[2]),o(*p),p+=3:*p==p[1]?o(137-*p++),o(*p++),p:(o(137-*p),o(*p++),p);}返回0;}
MATLAB(v7.8.0):
73个字符(不包括用于使其看起来可读的格式化字符)
此脚本(“haha.m”)假设您已经定义了变量n:
s = 'H';
for i = 1:n,
s = regexprep(s,'(H)(H|AA)?|(A)(AH)?','${[137-$1 $1]}');
end
…以下是一行版本:
s='H';for i=1:n,s = regexprep(s,'(H)(H|AA)?|(A)(AH)?','${[137-$1 $1]}');end
#include <stdio.h>
#include <string.h>
char s[99] = "H", t[99] = {0};
int main()
{
for(int n = 0; n < 10; n++)
{
int i = 0, j = strlen(s);
printf("n = %u | %s\n", n, s);
strcpy(t, s);
s[0] = 0;
/*
* This was originally just a while() loop.
* I tried to make it shorter by making it a for() loop.
* I failed.
* I kept the for() loop because it looked uglier than a while() loop.
* This is code golf.
*/
for(;i<j;)
{
if(t[i++] == 'H' )
{
// t[i] == 'H' ? i++ : t[i+1] == 'A' ? i+=2 : 1;
// Oh, ternary ?:, how do I love thee?
if(t[i] == 'H')
i++;
else if(t[i+1] == 'A')
i+= 2;
strcat(s, "AH");
}
else
{
// t[i] == 'A' ? i += 1 + (t[i + 1] == 'H') : 1;
if(t[i] == 'A')
if(t[++i] == 'H')
i++;
strcat(s, "HA");
}
}
}
return 0;
}
测试:
>> for n=0:10, haha; disp([num2str(n) ': ' s]); end
0: H
1: AH
2: HAAH
3: AHAH
4: HAAHHAAH
5: AHAHHA
6: HAAHHAAHHA
7: AHAHHAAHHA
8: HAAHHAAHHAAHHA
9: AHAHHAAHAHHA
10: HAAHHAAHHAHAAHHA
Perl
168个字符。
(不包括不必要的换行)
消除混淆:
Perl
150个字符。
(不包括不必要的换行)
消除模糊
Lex/Flex
69个字符。在这里的文本中,我将制表符改为8个空格,这样看起来就对了,但是所有这些连续的空格都应该是制表符,制表符很重要,所以总共有69个字符
#include <stdio.h>
%%
HAA|HH|H printf("AH");
AAH|AA|A printf("HA");
这会进行多次迭代(与上一次不同,上一次只进行了一次迭代,每次都必须手动设定种子,但会产生正确的结果),并且具有非常可怕的代码的优势。我使用一个函数宏、字符串化操作符和两个全局变量。如果您想要一个更混乱的版本,它甚至不检查malloc()
失败,它看起来像这样(282个字符):
我的首选是最有效的(即第一个可以迭代直到内存耗尽并检查其错误的),但这是代码高尔夫
要编译第一个,请键入:
flex golf.l
gcc -ll lex.yy.c
(如果您使用的是lex
而不是flex
,只需将flex
更改为lex
。它们应该是兼容的。)
要编译其他文件,请键入:
flex golf.l
gcc -std=c99 lex.yy.c
否则,GCC将抱怨C99模式之外使用的循环初始声明和其他废话
下面是纯C答案。Javascript:
120剥离空白,我现在就不管它了
function f(n,s){s='H';while(n--){s=s.replace(/HAA|AAH|HH?|AA?/g,function(a){return a.match(/^H/)?'AH':'HA'});};return s}
扩大:
function f(n,s)
{
s = 'H';
while (n--)
{
s = s.replace(/HAA|AAH|HH?|AA?/g, function(a) { return a.match(/^H/) ? 'AH' : 'HA' } );
};
return s
}
那个替代品很贵 ANSI C99
以306个字符的速度出现:
char*c,*t;
#define s(a) t=c?realloc(c,strlen(c)+3):calloc(3,1);if(t)c=t,strcat(c,#a);
%%
free(c);c=NULL;
HAA|HH|H s(AH)
AAH|AA|A s(HA)
%%
int main(void){c=calloc(2,1);if(!c)return 1;*c='H';for(int n=0;n<10;n++)printf("n = %d | %s\n",n,c),yy_scan_string(c),yylex();return 0;}int yywrap(){return 1;}
char*c,*t;
#define s(a) t=c?realloc(c,strlen(c)+3):calloc(3,1);c=t;strcat(c,#a);
%%
free(c);c=NULL;
HAA|HH|H s(AH)
AAH|AA|A s(HA)
%%
int main(void){c=calloc(2,1);*c='H';for(int n=0;n<10;n++)printf("n = %d | %s\n",n,c),yy_scan_string(c),yylex();return 0;}int yywrap(){return 1;}
#include <stdio.h>
#include <string.h>
char s[99]="H",t[99]={0};int main(){for(int n=0;n<10;n++){int i=0,j=strlen(s);printf("n = %u | %s\n",n,s);strcpy(t,s);s[0]=0;for(;i<j;){if(t[i++]=='H'){t[i]=='H'?i++:t[i+1]=='A'?i+=2:1;strcat(s,"AH");}else{t[i]=='A'?i+=1+(t[i+1]=='H'):1;strcat(s,"HA");}}}return 0;}
return new Regex("HAA|AAH|HH|AA|A|H").Replace(i,m =>(String)new Hashtable{{"H","AH"},{"A","HA"},{"AA","HA"},{"HH","AH"},{"AAH","HA"},{"HAA","AH"}}[m.Value]);
a='h';n.times{puts a.gsub!(/(h(h|aa)?)|(a(ah?)?)/){$1.nil?? "ha":"ah"}}
#包括
#包括
字符s[99]=“H”,t[99]=“0};int main(){for(int n=0;n这里有一个C#示例,如果我将每个项之间的空格减少到一个空格,则会得到321字节
编辑:作为对评论的回应,我从解决方案中删除了泛型以寻找更多的字节
编辑:另一个更改,删除了所有临时变量
public static String E(String i)
{
return new Regex("HAA|AAH|HH|AA|A|H").Replace(i,
m => (String)new Hashtable {
{ "H", "AH" },
{ "A", "HA" },
{ "AA", "HA" },
{ "HH", "AH" },
{ "AAH", "HA" },
{ "HAA", "AH" }
}[m.Value]);
}
重写后的解决方案的空白更少,但仍然可以编译,其长度为158个字符:
char*c,*t;
#define s(a) t=c?realloc(c,strlen(c)+3):calloc(3,1);if(t)c=t,strcat(c,#a);
%%
free(c);c=NULL;
HAA|HH|H s(AH)
AAH|AA|A s(HA)
%%
int main(void){c=calloc(2,1);if(!c)return 1;*c='H';for(int n=0;n<10;n++)printf("n = %d | %s\n",n,c),yy_scan_string(c),yylex();return 0;}int yywrap(){return 1;}
char*c,*t;
#define s(a) t=c?realloc(c,strlen(c)+3):calloc(3,1);c=t;strcat(c,#a);
%%
free(c);c=NULL;
HAA|HH|H s(AH)
AAH|AA|A s(HA)
%%
int main(void){c=calloc(2,1);*c='H';for(int n=0;n<10;n++)printf("n = %d | %s\n",n,c),yy_scan_string(c),yylex();return 0;}int yywrap(){return 1;}
#include <stdio.h>
#include <string.h>
char s[99]="H",t[99]={0};int main(){for(int n=0;n<10;n++){int i=0,j=strlen(s);printf("n = %u | %s\n",n,s);strcpy(t,s);s[0]=0;for(;i<j;){if(t[i++]=='H'){t[i]=='H'?i++:t[i+1]=='A'?i+=2:1;strcat(s,"AH");}else{t[i]=='A'?i+=1+(t[i+1]=='H'):1;strcat(s,"HA");}}}return 0;}
return new Regex("HAA|AAH|HH|AA|A|H").Replace(i,m =>(String)new Hashtable{{"H","AH"},{"A","HA"},{"AA","HA"},{"HH","AH"},{"AAH","HA"},{"HAA","AH"}}[m.Value]);
a='h';n.times{puts a.gsub!(/(h(h|aa)?)|(a(ah?)?)/){$1.nil?? "ha":"ah"}}
对于VisualStudio2008的完整源代码解决方案,下面提供了包含必要代码(包括单元测试)的subversion存储库
,用户名和密码都是“guest”,没有引号。在python中:
def l(s):
H=['HAA','HH','H','AAH','AA','A']
L=['AH']*3+['HA']*3
for i in [3,2,1]:
if s[:i] in H: return L[H.index(s[:i])]+l(s[i:])
return s
def a(n,s='H'):
return s*(n<1)or a(n-1,l(s))
for i in xrange(0,10):
print '%d: %s'%(i,a(i))
def l(s):
H=['HAA','HH','H','AAH','AA','A']
L=['AH']*3+['HA']*3
对于[3,2,1]中的i:
如果H中的s[:i]:返回L[H.索引(s[:i])]+L(s[i:]
返回s
定义a(n,s='H'):
返回s*(nRuby
这段代码并没有很好地指定——我假设返回第n个迭代字符串的函数是解决它的最佳方法。它有80个字符
def f n
a='h'
n.times{a.gsub!(/(h(h|aa)?)|(a(ah?)?)/){$1.nil?? "ha":"ah"}}
a
end
打印出n个前字符串(71个字符)的代码:
Erlang
241字节,准备运行:
> erl -noshell -s g i -s init stop
AHAHHAAHAHHA
-module(g).
-export([i/0]).
c("HAA"++T)->"AH"++c(T);
c("AAH"++T)->"HA"++c(T);
c("HH"++T)->"AH"++c(T);
c("AA"++T)->"HA"++c(T);
c("A"++T)->"HA"++c(T);
c("H"++T)->"AH"++c(T);
c([])->[].
i(0,L)->L;
i(N,L)->i(N-1,c(L)).
i()->io:format(i(9,"H"))
可能会有所改进。Python(150字节)
输出
n=0 | H
n=1 |啊
n=2 |哈
n=3 |啊哈
n=4 |哈哈哈
n=5 | ahaha
n=6 |哈哈哈
n=7 |啊哈啊哈
n=8 |哈哈哈哈哈
n=9 |哈哈哈哈哈
REBOL,150个字符。不幸的是,REBOL不是一种有助于编码高尔夫的语言,但正如亚当·桑德勒所说,150个字符并不太寒酸
这假设已经定义了循环变量m
s: "H" r: "" z:[some[["HAA"|"HH"|"H"](append r "AH")|["AAH"|"AA"|"A"](append r "HA")]to end]repeat n m[clear r parse s z print["n =" n "|" s: copy r]]
s:“H”r:“z:[一些[“HAA”|“HH”|“H”](附加r“AH”)|[“AAH”|“AA”|“A”](附加r“HA”)]结束]重复n m[清除r解析s z打印[“n=”n“|”s:复制r]]
这里有更好的布局:
s: "H"
r: ""
z: [
some [
[ "HAA" | "HH" | "H" ] (append r "AH")
| [ "AAH" | "AA" | "A" ] (append r "HA")
]
to end
]
repeat n m [
clear r
parse s z
print ["n =" n "|" s: copy r]
]
s:“H”
r:“”
z:[
一些[
[“HAA”|“HH”|“H”](附加r“AH”)
|[“啊”|“AA”|“A”](附加r“HA”)
]
结束
]
重复n-m[
清除r
解析sz
打印[“n=”n“|”s:copy r]
] F#:184个字符
似乎很清楚地映射到F#:
以下是fsi中的运行:
> [for a in 0 .. 9 -> a, laugh(a, [H])] |> Seq.iter (fun (a, b) -> printfn "n = %i: %A" a b);;
n = 0: [H]
n = 1: [A; H]
n = 2: [H; A; A; H]
n = 3: [A; H; A; H]
n = 4: [H; A; A; H; H; A; A; H]
n = 5: [A; H; A; H; H; A]
n = 6: [H; A; A; H; H; A; A; H; H; A]
n = 7: [A; H; A; H; H; A; A; H; H; A]
n = 8: [H; A; A; H; H; A; A; H; H; A; A; H; H; A]
n = 9: [A; H; A; H; H; A; A; H; A; H; H; A]
我不知道,但我很惊讶它竟然被关闭了,因为有一大堆相同的“代码高尔夫”一个。我不知道,但为什么这些没有关闭?@Zifre,我个人很想看看这是如何在几种语言中以紧凑的方式完成的。我正在使用lex想出一个奇怪的解决方案。我真的希望在我完成它之前不会关闭它。+1这很有趣,我很高兴boredI打算用lex/C以类似的方式来完成它(我认为这更容易),但实际上这在C++中是非常简单的,有几个宏。我的目标是最小化最小值:)我必须承认我不熟悉Lex,所以我想知道)你的代码是如何通过初始化字符串到“H”和B来开始的。如何让它停止在给定的n?我很懒-代码只进行一次迭代。我很快会想出如何编写更好的版本,但现在你输入“H”,它会吐出“AH”,然后你输入“AH”,它会吐出“HAAH”,等等。我会在某个时候用合适的解决方案进行编辑,这非常复杂。无论如何,要编译这段代码,键入“flex file.l”,它将生成文件“lex.yy.c”。用c编译器编译它,并链接到lex库(很可能是libl.a)这似乎是到目前为止我接受的最短的一个。我从来不知道matlab代码可以如此浓缩。我投票给了所有有过它的人
> erl -noshell -s g i -s init stop
AHAHHAAHAHHA
-module(g).
-export([i/0]).
c("HAA"++T)->"AH"++c(T);
c("AAH"++T)->"HA"++c(T);
c("HH"++T)->"AH"++c(T);
c("AA"++T)->"HA"++c(T);
c("A"++T)->"HA"++c(T);
c("H"++T)->"AH"++c(T);
c([])->[].
i(0,L)->L;
i(N,L)->i(N-1,c(L)).
i()->io:format(i(9,"H"))
import re
N = 10
s = "H"
for n in range(N):
print "n = %d |"% n, s
s = re.sub("(HAA|HH|H)|AAH|AA|A", lambda m: m.group(1) and "AH" or "HA",s)
n = 0 | H
n = 1 | AH
n = 2 | HAAH
n = 3 | AHAH
n = 4 | HAAHHAAH
n = 5 | AHAHHA
n = 6 | HAAHHAAHHA
n = 7 | AHAHHAAHHA
n = 8 | HAAHHAAHHAAHHA
n = 9 | AHAHHAAHAHHA
s: "H" r: "" z:[some[["HAA"|"HH"|"H"](append r "AH")|["AAH"|"AA"|"A"](append r "HA")]to end]repeat n m[clear r parse s z print["n =" n "|" s: copy r]]
s: "H"
r: ""
z: [
some [
[ "HAA" | "HH" | "H" ] (append r "AH")
| [ "AAH" | "AA" | "A" ] (append r "HA")
]
to end
]
repeat n m [
clear r
parse s z
print ["n =" n "|" s: copy r]
]
type grammar = H | A
let rec laugh = function
| 0,l -> l
| n,l ->
let rec loop = function
|H::A::A::x|H::H::x|H::x->A::H::loop x
|A::A::H::x|A::A::x|A::x->H::A::loop x
|x->x
laugh(n-1,loop l)
> [for a in 0 .. 9 -> a, laugh(a, [H])] |> Seq.iter (fun (a, b) -> printfn "n = %i: %A" a b);;
n = 0: [H]
n = 1: [A; H]
n = 2: [H; A; A; H]
n = 3: [A; H; A; H]
n = 4: [H; A; A; H; H; A; A; H]
n = 5: [A; H; A; H; H; A]
n = 6: [H; A; A; H; H; A; A; H; H; A]
n = 7: [A; H; A; H; H; A; A; H; H; A]
n = 8: [H; A; A; H; H; A; A; H; H; A; A; H; H; A]
n = 9: [A; H; A; H; H; A; A; H; A; H; H; A]