3 个版本
0.0.3 | 2024年2月24日 |
---|---|
0.0.2 | 2024年2月17日 |
0.0.1 | 2024年2月17日 |
#348 在 数学
每月 105 次下载
50KB
1K SLoC
spin4
spin4 是一种使用 4D 旋转进行计算的谜之编程语言。其主要哲学是通过旋转编码状态的 4D 空间来编写程序,然后使用此状态来递增或递减累加器向量。累加器组件可以放入堆栈中,堆栈也可以向一个方向旋转。
为什么?
是的。
spin4 解释器
当前的 spin4 解释器尚未优化,仅作为概念证明。安装
cargo install spin4
Usage: spin4 [OPTIONS] --file <FILE>
Options:
-f, --file <FILE>
-d, --debug
-h, --help Print help
-V, --version Print version
基本概述
最终,一个 spin4 程序具有
- 一个包含 2 个组件的累加器向量:寄存器 X 和 Y
- 我们通过执行加法、减法、乘法或整数除法来进行旋转以累积值
- 我们可以对其组件 X 进行操作,
- 当我们旋转 4D 空间时,堆栈的值会增加或减少
- 一个堆栈
- 我们可以逐个组件地将累加器的值推入,即推入 X 或 Y 的值
- 我们可以使用标准输入执行推入
- 我们可以从左或右旋转它
- 我们可以将顶部元素弹出到一个寄存器中
- 我们可以显示顶部元素
示例
Hello World
spin4 中的 Hello World 程序
{(+1>)x?y}(+0000>)*[<][<][y]y[>][>][x]x*[>][>][y]y[<][<][x]+[x]+[.c][x]x+[x]+[x]+[x]+[<][yx]y[>]-(+1054<5401>012111<)x(+0>)x[.c][<][<][<][<][yx]xy[>][>][>][>]+[xy]y+[.c][.c][x]x[<][<][<][y]y[>][>][>]+[.c][x]x+[>][>][x]x[<][y]x[<][<][<][<][<][<][.c][<][<][.c]y[.c][y][xy][yx][xy][y][.c][xy][.c][yx][.c]
斐波那契序列
作为传统,这里是在 spin4 中的斐波那契序列。此程序接收一个正整数 n 作为输入(stdin)并打印 n 个第一个斐波那契数的列表。
[,n](+00>)y*[y]*[x]*[>][x](-00<)(+0>)xxx[.n][<][.c][>][.n][xy]xy{[xy]+x[xy]xy[<][.c][>][.n][>][>][yx]y-[yx]yx[>][>][>]?y}
概念
旋转 < -π/2 和 > +π/2
在 4D 中,我们可以从基向量形成总共 6 个平面,旋转平面是 2D 中旋转中心的等效概念,即在 4D 旋转下始终有一个不变的平面。
- xy 作为
0
(xy 平面是不变的) - xz 作为
1
(xz 平面是不变的) - xw 作为
2
(xw 平面是不变的) - yz 作为
3
(yz 平面是不变的) - yw 作为
4
(yw 平面是不变的) - zw 作为
5
(zw 平面保持不变)
-
我们使用语法
(main_operator seq_of_rotation)
开始旋转或旋转序列 -
旋转后累加器会发生什么?
- 累加器向量状态改变:X 和 Y 增量/减少
- 系统以某种方式变得有方向
- 从概念上讲,为了计算累加器向量的下一个状态,spin4 采取两个仅能生成与 $\vec{u} = (1 \space 0 \space 0 \space 0)^T$ 和 $\vec{v} = (0 \space 1 \space 0 \space 0)^T$ 相同平面的基本向量。例如,如果我们有系统矩阵中的列 $(0 \space -1 \space 0 \space 0)^T$ 和 $(1 \space 0 \space 0 \space 0)^T$,则方向签名变为
[-1, 1]
,然后我们可以计算下一个累加器状态acc <- acc + [-1, 1]
。
计算签名的最简单实现是遍历满足投影 $\vec{u}.\vec{v}'=0$ 和 $\vec{u}'.\vec{v}=0$ 的每个列对组合 $(\vec{u}', \vec{v}')$,这基本上保证了生成的平面与初始平面相似。
一个不错的技巧是注意到,在单位矩阵或其列的符号排列上应用 $\pm \pi / 2$ 旋转始终会产生一个 广义排列矩阵,其非零项为
-1
和1
,我们可以通过一些代数简单地提取相关项。
$$T \leftarrow R_{Index, Dir} T$$
$$ (Acc_X \space Acc_Y) \leftarrow (Acc_X \space Acc_Y) + \begin{pmatrix}1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0\end{pmatrix} T \begin{pmatrix}1 \\ 1 \\ 1 \\ 1\end{pmatrix} $$
指令
-
算术运算符
+
,-
,/
,*
,_
(无操作)。 -
旋转序列
(Op Seq)
Op
可以是上述任何二元运算符Seq
是一系列有序旋转
例如,(+1>1<01>)
等价于(+01>)
-
x
或y
:将累加器的特定组件推送到堆栈中。
示例(+03<5>)x
=> 将 -1 推送到堆栈,累加器[-1, 1]
- 堆栈 := ... -1
(+03<5>)yx
=> 将 1 和 -1 压入栈中,累加器[-1, 1]
- 栈 := ... 1 -1
(+03<5>)*
=> 将 -1(或 x=-1 * y=1)压入栈中,累加器[-1, 1]
- 堆栈 := ... -1
(+03<5>)x+y
=> 将 -1、0、1 压入栈中,累加器向量是[-1, 1]
- 栈 := ... -1 0 1
(+03<5>)yx/+x
=> 将 1, -1, -1, 0, 然后是 -1 压入栈中,累加器[-1, 1]
- 栈 := ... 1 -1 -1 0 -1
-
[>]
/[<]
: 右/左旋转栈 -
[x]
,[y]
,[xy]
或[yx]
: 弹出栈中的值,按顺序放入相应的累加器组件 -
[.n]
: 打印栈顶元素作为数字 -
[.c]
: 打印栈顶元素作为字符 -
[,n]
: 数字输入(int32) -
[,c]
: 字符输入 -
循环
{ .. ?t}
:t 是 x 或 y,它检查单个累加器组件,如果值为 0 则中断循环。示例
{(+50>)?x}y
当累加器 x 的分量是 0 时停止,然后将 y 分量值推送到堆栈
更多示例...
-
示例 1:操作符
no op
_
在某些情况下,我们只想执行一系列旋转,而在这个过程中不执行任何操作。在表达式
(_03>5<)
中,累加器向量保持为[0, 0]
。 -
示例 2:在旋转时执行加法/减法...
考虑以下程序
(+03<5>)
- 旋转 0(90 度),根据与初始 xy 对应的平面方向执行加法
- acc = [0, 0]
+
[+1, +1] = [1, 1]
- acc = [0, 0]
- 旋转 3(90 度),根据与初始 xy 对应的平面方向执行加法
- acc = [1, 1]
+
[-1, +1] = [0, 2]
- acc = [1, 1]
- 旋转 5(-90 度),根据与初始 xy 对应的平面方向执行加法
- acc = [0, 2]
+
[-1, -1] = [-1, 1] 因此,累加器向量变为 [-1, 1]
- acc = [0, 2]
- 旋转 0(90 度),根据与初始 xy 对应的平面方向执行加法
-
示例 3
设
acc = [2, 4]
程序中的
+
.. + ..
计算 2 + 4,结果存储在堆栈中。 -
示例 4
表达式
(-01>3<)x
中的x
提取累加器的 x 分量并将其存储在堆栈中。
依赖项
~4.5MB
~92K SLoC