逻辑与代码 2

转载自:https://mp.weixin.qq.com/s/jIVa_mmqHiqSloqyDhsimQ

4、格雷码

在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同,则称这种编码为格雷码(Gray Code)下面看下格雷码和普通二进制码的区别

十进制数      二进制码         4位格雷码

 0                 0000                 0000

 1                 0001                 0001

 2                 0010                 0011

 3                 0011                 0010

 4                 0100                 0110

 5                 0101                 0111

 6                 0110                 0101

 7                 0111                 0100

 8                 1000                 1100

 9                 1001                 1101

10                 1010                 1111

11                 1011                 1110

12                 1100                 1010

13                 1101                 1011

14                 1110                 1001

15                 1111                 1000

 

1  gray(1,['_','X']).

2  gray(N,C) :- 

3 N > 1,

4 N1 is N-1, 

5 gray(N1,C1),

6 write('N1 = '),write(N1),nl,

7 reverse(C1,C2),

8 write('C1 = '),write(C1),nl,

9 write('C2 = '),write(C2),nl,

10 prepend('_',C1,C1P),

11 prepend('X',C2,C2P),

12 write('C1P = '),write(C1P),nl,

13 write('C2P = '),write(C2P),nl,

14 append(C1P,C2P,C).

15

 

注释行:

1.  当只有一位码时的列表,初始值

2.  

3.  确保N是大于1的

4.  将N减1赋给N1

5.  先递归到最小,从只有1位码的情况开始返回

6.  调式用代码行

7.  将列表C1反转到列表C2

8.  调式用代码行

9.  调式用代码行

10. 处理列表中的元素

11. 处理列表中的元素

12. 调式用代码行

13. 调式用代码行

14. 将C1P和C2P列表拼接到列表C

15. 空行

 

16 prepend(_,[],[]) :- !.

17 prepend(X,[C|Cs],[CP|CPs]) :- 

18 atom_concat(X,C,CP),

19 prepend(X,Cs,CPs).

20

 

 

注释行:

16. 自己来填

17. 。。。。

18. 将原子X拼接到原子C的前面结果到CP

19. 递归处理后续元素

20. 空行

 

请仔细体会有调试行指示输出的代码:

?- consult('p3_04').

true.

 

?- gray(3,C),write(C).

N1 = 1

C1 = [0,1]

C2 = [1,0]

C1P = [00,01]

C2P = [11,10]

N1 = 2

C1 = [00,01,11,10]

C2 = [10,11,01,00]

C1P = [000,001,011,010]

C2P = [110,111,101,100]

[000,001,011,010,110,111,101,100]

C = ['000', '001', '011', '010', '110', '111', '101', '100'] .

 

?- 

 

谓词gray_c/2.用缓存技术做个示例

 

21 :- dynamic gray_c/2.

 

22 gray_c(1,['0','1']) :- !.

23 gray_c(N,C) :- 

24 N > 1, N1 is N-1,

25 gray_c(N1,C1),

26 reverse(C1,C2),

27 prepend(‘0',C1,C1P),

28 prepend(‘1',C2,C2P),

29 append(C1P,C2P,C),

30 asserta((gray_c(N,C) :- !)).

31

% Try the following goal sequence and see what happens:

 

% ?- [p3_04]. 

% ?- listing(gray_c/2).

% ?- gray_c(5,C).

% ?- listing(gray_c/2).

 

 

 

注释行:

21. %设置为动态谓词(运行时可以动态增删)

22. %自己来填

23. %确保N大于1,然后N减1后赋值给N1

24. 

25. %递归处理剩余位

26. %将C1反转后给到C2

27. %将字符’0’和原子C1拼接

28. %将字符’1’和原子C2拼接

29. %将C1P和C2P列表拼接到列表C

30. %将事实gray_c/2动态添加到当前事实数据库

31. 空行

 

实际做个查询来看看效果是怎样的:

?- consult('p3_04').

true.

 

?- listing(gray_c/2).

:- dynamic gray_c/2.

 

gray_c(1, ['0', '1']) :-

    !.

gray_c(N, C) :-

    N>1,

    N1 is N+ -1,

    gray_c(N1, C1),

    reverse(C1, C2),

    prepend('0', C1, C1P),

    prepend('1', C2, C2P),

    append(C1P, C2P, C),

    asserta((gray_c(N, C):-!)).

 

true.

 

?- gray_c(5,C).

C = ['00000', '00001', '00011', '00010', '00110', '00111', '00101', '00100', '01100'|...].

 

?-  listing(gray_c/2).

:- dynamic gray_c/2.

 

gray_c(5, ['00000', '00001', '00011', '00010', '00110', '00111', '00101', '00100', '01100', '01101', '01111', '01110', '01010', '01011', '01001', '01000', '11000', '11001', '11011', '11010', '11110', '11111', '11101', '11100', '10100', '10101', '10111', '10110', '10010', '10011', '10001', '10000']) :-

    !.

gray_c(4, ['0000', '0001', '0011', '0010', '0110', '0111', '0101', '0100', '1100', '1101', '1111', '1110', '1010', '1011', '1001', '1000']) :-

    !.

gray_c(3, ['000', '001', '011', '010', '110', '111', '101', '100']) :-

    !.

gray_c(2, ['00', '01', '11', '10']) :-

    !.

gray_c(1, ['0', '1']) :-

    !.

gray_c(N, C) :-

    N>1,

    N1 is N+ -1,

    gray_c(N1, C1),

    reverse(C1, C2),

    prepend('0', C1, C1P),

    prepend('1', C2, C2P),

    append(C1P, C2P, C),

    asserta((gray_c(N, C):-!)).

 

true.

 

?- 

 

构造格雷码还可以用另一种方式定义:

32 gray_alt(1,['0','1']).

33 gray_alt(N,C) :- 

34 N > 1, 

35 N1 is N-1,

36 gray_alt(N1,C1), 

37 postpend(['0','1'],C1,C).   

38

 

注释行:

32. 当只有一位码时的列表,初始值

33

34. 确保N大于1,

35. N减1后赋值给N1

36. 递归处理后续元素

37. 

38. 

 

38 postpend(_,[],[]).

40 postpend(P,[C|Cs],[C1P,C2P|CsP]) :- 

41 P = [P1,P2],

42 atom_concat(C,P1,C1P), 

43 atom_concat(C,P2,C2P),

44 reverse(P,PR),

45 postpend(PR,Cs,CsP).

46

 

 

注释行:

 

39.  终止条件

40. 

41. P是列表[0,1]或[1,0]即[P1,P2]

42. 将字符P1接到原子C的后面,结果给到C1P,字符本身也是原子

43. 将字符P2接到原子C的后面,结果给到C2P

44. 反转列表P到PR

45. 用列表PR去递归调用处理后续的原子

46. 空行

 

再观察一下运行结果:

?- 

|    consult('p3_04').

true.

 

?- gray_alt(5,C),write(C).

[00000,00001,00011,00010,00110,00111,00101,00100,01100,01101,01111,01110,01010,01011,01001,01000,11000,11001,11011,11010,11110,11111,11101,11100,10100,10101,10111,10110,10010,10011,10001,10000]

C = ['00000', '00001', '00011', '00010', '00110', '00111', '00101', '00100', '01100'|...] .

 

?- 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值