我正在通过逻辑基础课程,并陷入了基础知识的最后摘要:
具有二进制数,将转换器写入其一元表示形式:
Inductive bin : Type :=
| Z
| A (n : bin)
| B (n : bin).
Fixpoint bin_to_nat (m:bin) : nat :=
(* What to do here? *)
我用C中的递归函数解决了这个问题。唯一的事情是,我使用“ 0”代替“ A”,而不是“ 1”代替“ B”。
#include <stdio.h>
unsigned int pow2(unsigned int power)
{
if(power != 0)
return 2 << (power - 1);
else
return 1;
}
void rec_converter(char str[], size_t i)
{
if(str[i] == 'Z')
printf("%c", 'Z');
else if(str[i] == '0')
rec_converter(str, ++i);
else if(str[i] == '1')
{
unsigned int n = pow2(i);
for (size_t j = 0; j < n; j++)
{
printf("%c", 'S');
}
rec_converter(str, ++i);
}
}
int main(void)
{
char str[] = "11Z";
rec_converter(str, 0);
printf("\n");
return 0;
}
我现在的问题是如何在coq中编写此代码:
unsigned int n = pow2(i);
for (size_t j = 0; j < n; j++)
{
printf("%c", 'S');
}
rec_converter(str, ++i);
答案 0 :(得分:4)
您的代码与Coq代码之间的主要区别在于,Coq代码应该返回自然数,而不是打印自然数。这意味着我们需要跟踪解决方案打印的所有内容,并一次返回所有结果。
由于打印S
意味着答案是打印其他任何内容的后继者,因此我们需要一个函数,该函数可以接受自然数的第2 ^(n)个后继者。有多种方法可以执行此操作,但是我建议对n进行递归,并注意x的第2 ^(n + 1)个后继者是x的第2 ^(n)个继任者的第2 ^(n)个继任者。 x。
那应该足以满足您的需求。
unsigned int n = pow2(i);
for (size_t j = 0; j < n; j++)
{
printf("%c", 'S');
}
rec_converter(str, ++i);
可以写为(pseudo-Coq)
pow2_succ i (rec_converter str (S i)).
但是,还有另一件事要注意:您可能无法直接访问输入的第i个“字符”,但这应该不是问题。当您将函数编写为Fixpoint
Fixpoint rec_converter (n: bin) (i: nat): nat :=
match n with
| Z => 0
| A m => ...
| B m => ...
end.
m的第一个“字符”将是原始输入的第二个“字符”。因此,您只需要访问第一个“字符”,这正是Fixpoint
的作用。
答案 1 :(得分:2)
对于2的计算能力问题,您应该查看Coq库中提供的以下文件(至少在8.9版之前):
https://coq.inria.fr/distrib/current/stdlib/Coq.Init.Nat.html
此文件包含许多围绕自然数的函数,它们都可以用作说明如何使用Coq和此数据类型进行编程的例子。
答案 2 :(得分:0)
Fixpoint bin_to_nat (m:bin) : nat :=
match m with
| Z => O
| A n =>2 * (bin_to_nat n)
| B n =>2 * (bin_to_nat n) + 1
end.
参见:coq art's2004。P167-P168。 (如何理解Coq中的“阳性”类型)