偷得浮生半日闲

上周的线代,这周的数分。一门接一门地崩坏,粉碎,爆炸,散裂。

可能现实并没想象中的那么糟糕,然而这份对过去那个偷懒自我的愧责难以消弭…悲观,往往来自自己的不作为。

一种思想,一个点子,如果在意识空间里萌发,就无法被扼杀:每一次扼杀的企图,都会使点子扎根更牢、更深;只能被淡忘,或漠视。

悲剧或许正是悲情的不断螺旋,是意识空间到现实时空的投射——反而又成为了自我预言的实现。

讨厌考试,讨厌的不止结果,更有整段历史。紧张、焦虑便是一切的预言。


考完第一件事便是打开群聊,企图用他人的悲剧弥补内心的空洞。“原来别人也和我一样啊”的说辞或少能给予些许安慰,但改变不了历史,也改变不了自责,只是一针麻剂。

点开屏幕,第一条竟是袁老逝世的消息。顿时不敢相信自己的眼睛。

袁老高龄九十一了啊。

幼时记忆在大脑中意外地不受时间约束——仿佛那位田间老农、那个灿烂的笑容和那捧金灿灿的稻子、那个矮小精瘦的身躯,还在昨日电视、报刊。

院士爷爷,一路走好。


是啊,只有时间,是不可挽回的。只有昨日,是不可再见的。

逝者难追,还是要好好学习啊。

吾心便是宇宙。无愧天地,更无愧我心。


有的人死了,他还活着。

有的人活着,但他已经死了。


明天考电磁,无心复习。

或许是物竞的ptsd。可能是因为一打开书本就下意识的想起高中岁月。怀念与悔恨并存,内心空荡荡的。像窗外夏季的热风,刮进了明朗破败的空房…胃疼。

图书馆挺热,挺静。

甚至有时候觉得,就这么固步自封也不错。

坐着,看看窗外蓝天碧树、世间嘈杂,也不错。偷得浮生半日闲,好喘口气歇歇,好看着想逃跑的时间。

如果有空了,我定要坐下来,好好发发呆。

现在想想,最闲的竟是高考前的那段岁月,次闲的是近几天期中考的这段时间。

然而人总不能在时间中停滞。

诗和远方,在路上。

以上,算是对过去的总结吧。

一点感触

宇宙在膨胀,熵在增,人与人的时间线在疏远

不要让那些关心你的人担心啊…多打电话多联系

内心的空如点燃的纸洞

源于摩擦后的小火星、涨落中的小火苗

或许是又一种自我预言的实现

最终被填充物慢慢撑大


乐观不应是自我欺骗自我逃避

尽人事方能知天命

坠落、堕落

无论多深,终有浮力

好好学习、天天向上

做最好的自己

如何不用洋文编程

不用洋文生成前一百个素数

前些天学了点js,发现里边的箭头函数是真的好用,从此function关键字消失在了我的代码中。

但随之也发现了个问题,匿名函数遇上需要递归的地方该咋办呢……

在谷歌上不抱任何期待地敲下“匿名函数”“递归”等字样,没想到还真的有这样的操作。

Github上的大佬给出了答案。

https://github.com/Lucifier129/Lucifier129.github.io/issues/7 在 JavaScript

在 JavaScript 中用匿名函数(箭头函数)写出递归的方法

看起来还不错,越看越亢奋(装作看懂了的样子)

根据教程里的指导,求一个数阶乘可以写成这样的形式:

var fact_fac = self => num => num ? num * self(--num) : 1;
var Y = f => (x => n => f(x(x))(n))(x => n => f(x(x))(n));
var fact = Y(fact_fac);
console.log(fact(4));//24

解释一下:

先看第一行,

对于任意的函数self,这里边的fact_fac(源自factorial factory,阶乘工厂)满足

fact_fac(self) <=> num => num ? num * self(--num) : 1;

那么,当self为fact,其中fact也就是我们要的阶乘函数时,神奇的事情发生了!

fact_fac(fact) <=> num => num ? num * fact(--num) : 1;

而后者恰恰时fact函数的实现!!

这意味着有

fact_fac(fact) <=> fact

那么求解fact也就意味着要求解fact_fac的不动点。

而这,恰恰可以由另一个神奇的Y函数求得。具体实现可以自行维基Y组合子以及λ演算。

到这里,你会发现借助Y函数,所有的递归函数都可以用匿名函数表示,具体实现起来就是这样:

function a (...){
    ...a(...)...
    return b;
}

可以等价于

Y = f => (x => n => f(x(x))(n))(x => n => f(x(x))(n));
a = Y(self => (...) => {
    ...self(...)...
    return b;
});

那跟我们的主题“如何不用洋文编程”有什么关系呢?

别急,现在我们已经完成了第一步,彻底摆脱了function关键字。

稍微改造下上述代码,用$和_的组合代替变量名来装逼摆脱洋文。

(标点符号怎么能算洋文呢的!(~ ̄▽ ̄)~)

Y = $_=>(_=>$=>$_(_(_))($))(_=>$=>$_(_(_))($));
a = Y($=>(...)=>{...$(...)...return b;});

(当然,还有糟糕的return,这个呆会搞掉)

事实上,进一步了解js里的匿名函数后可以发现,它与lambda函数完全一致。

而lambda演算时图灵完备的,

这意味着我们的终极目标(不用洋文编程)是可行的!!


第二个需要解决的问题是循环的操作。

但是我们已经有了递归,解决一个while循环并不难。

直接上代码吧。

const Y = f => (x => n => f(x(x))(n))(x => n => f(x(x))(n));
const while_ = Y(self => judge => dosth => judge() && dosth() ^ self(judge)(dosth));

调用的基本语法是

while(a){b} <=> while_(()=>a)(()=>{b})

具体应用如下:

var test = 5;
while_(() => test > 0)(() => {
    console.log('yes!!!');
    test--;
});

简化一下:

const while_ = ($_=>(_=>$=>$_(_(_))($))(_=>$=>$_(_(_))($)))($=>_=>_$=>_()&&_$()^$(_)(_$));

当然也有相应的for循环版本:

const for_ = ($_=>(_=>$=>$_(_(_))($))(_=>$=>$_(_(_))($)))($=>_=>__=>$_=>_$=>{(_&&_())^__()&&_$()^$_()^$()(__)($_)(_$)});

调用的基本语法是:

for(a;b;c){d} <=> for_(()=>{a})(()=>b)(()=>{c})(()=>{d})

嫌for太丑太长,甚至自己造了个repeat函数,重复指定代码若干次。

const Y = f => (x => n => f(x(x))(n))(x => n => f(x(x))(n));
const repeat_ = Y(self => num => func => num && self(--num)() ^ func());
const repeat_ = ($_=>(_=>$=>$_(_(_))($))(_=>$=>$_(_(_))($)))($=>__=>_=>__&&$(--__)(_)^_());

相当于:

for(var i=0;i<a;i++){b/*without using i*/} <=> repeat_(a)(()=>{b})

OK,到此为止解决循环。


下一个问题是如何解决if等条件判断,这个好办,基本也有以下两种解决方案:

一种是三目运算符?:——不多说了。

另一种是利用&&和||以及&,|,^的性质:

if(a){b} <=> a&&b;
if(a){b}else{c} <=> a&&(b||1)||c;

1太丑,可以换成!0

两个语句间的分号也可以换成|、&、^等符号。

之前说的return也可以在这里解决。

注意到箭头函数箭头后可以直接返回值,那么可以采用以下的替换:

(a)=>{b; return c;} <=> (a)=>(b)&&0||c

善用++,可以让代码更简洁。


基本的操作就这些了,最后贴上开头处图片中的代码,欢迎大佬破译:

primes_below=$_$=>($=[])&($_=$)&(__=[])|(_=__)|_++^++_|($_=>(_=>$=>$_(_(_))($))(_=>$=>$_(_(_))($)))($=>_=>_$=>_()&&_$()^$(_)(_$))(()=>_<=$_$)(()=>{(_$=0)&(!__[_]&&($[$_++]=_))^($_=>(_=>$=>$_(_(_))($))(_=>$=>$_(_(_))($)))($=>_=>_$=>_()&&_$()^$(_)(_$))(()=>_$<=$_&&_*$[_$]<=$_$&&(_$==0||_%$[_$-!0]))(()=>{(__[_*$[_$]]=!0)|_$++})^_++})&&0||$;
console.log(primes_below(100));

PS. 切记,所有代码改写策略都要在非严格模式下执行,否则对变量的定义行为会产生洋文。

Screeps 第一周小结

从2月18日购买screeps至今已经有近一周了,写些东西备忘。

当初听说有这样的编程游戏还激动了好一阵子,可惜我太菜,犹豫了好久才下的单。

为了玩screeps,寒假还特意学了点js。还好js的语法与c差不多。

(顺便一提,js的箭头函数和弱变量类型是真的舒服,但也经常会有些奇怪的操作,总之很迷)

Picture from Johnson

人生第一次把api文档啃得那么仔细,为了建个能跑的脚本还反复过了好几遍的教程。

几天后的版本便能自动挖矿、升级、修路、刷墙了。

还在我的家(E17N28)击败了第一个侵略者,并收获了它的遗产。

甚至拓展了第二间room,开启了外矿之路。

感觉还是挺自豪的……

直到有人拆了我隔壁邻居的家,强占了他的room。

一看rcl等级,才3,不过如此——我都上5了。

碰巧敌人的防御creep是个憨憨。

这仇,必须得报。

进攻废了点功夫,不过,我还是占领了第三间room。

敌人被我赶跑,缩在自己老巢。

(有一说一,那个老巢地势真的好,易守难攻,我当初咋就没看见呢……E17N29)


夜深了,

我心满意足地睡觉去了……

第二天醒来,

发现家没了。

。。。

顿时人比前一天抽胡桃专武时歪了天空枪还难受……

。。。

好吧,一样难受。。。

我的家啊。。。


赶紧调录像,发现是我代码的一个逻辑bug。

当占领的room里的creep不断被干掉时,我的家会不断刷新creep。

导致自己把自己饿死了……

事前也想到过这种情况,但没想到的是,紧急搬运能量的creep也会由于能量不够,造不出来……

明明storage里还有300K的能量啊……

如果发现了这个问题,,

如果昨晚没为了进攻隔壁而把自家刷了好久的wall改建成rampart,,

如果睡前给新room开个安全模式,,

如果之前记得设置了自动安全模式打开机制,,

如果当时没贪、没懒,,

如果……


一个小bug或许短时间不会暴露出来,但一连串的小bug能拆了一个家。

这或许正是这个游戏的挑战之处。

毕竟coding一时爽,一直coding一直爽,debug火葬场。

总结教训:

在没有足够把握时,还是默默刷墙吧。

我的编程技巧暂时还支撑不起这个游戏。

这个寒假暂时退坑了。

厚积,薄发。

回顾2020 展望2021

终日乾乾,夕惕若厉

第一次选考

国科大冬令营 物之道 北方的冬天

疫情 停课 腾讯课堂 知乎

王裔平 铭校

作文素材 英语好词 apple的笔记

数海漫游 数学网课 模拟卷

汽车 公路 逆风而行 高楼蝼蚁

英语练字 5楼教室 乐正绫 地铁工地 远方

天命

憨憨的 傻不拉叽的 脸 手 颈 毕业了

租借女友 裸考的物理 迟到的高考

三一 鄞中 上海 复旦

国科大 分别 家 宿舍

孤月 大学生

深秋 落叶 初雪 寒风 卷

深夜 教学楼 操场 球

教室 寝室 食堂

消愁

原神 安柏 刻晴 胡桃

跨年 人类一败涂地


Flag

1. 11点前不打游戏,11点后不吃东西

2. 自习去教学楼或图书馆

3. 1点半前必须上床,睡前刷牙,睡时锁手机

4. 最晚10点起床,必须吃早餐

5. 不要活在过去的影子之中,学会反省,学会思考

0. 终日乾乾,夕惕若厉。自律,慎独,不自欺。


贪吃蛇 – 100行版本

简介

高一时受学校图形计算器上原装贪吃蛇程序启发而写的C++小游戏

高三时整理压缩至100行

代码

//By Eric Jin 2018     编译后切换至英文  a左d右w上s下       使用了Sleep() _kbhit() _getch() system("cls")等
#include <iostream> 
#include <sstream>
#include <string>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
#include <windows.h>
std::string o(int i)//4左6右8上2下
{
	if (i == 0) return "  ";
	else if (i == 1) return "# ";
	else if (i == 3) return "$ ";
	else return "* ";
}
void drawmap(int h, int l, int maptest[100][100])//绘图
{
	std::stringstream ss;
	for (int i = 1; i <= h; i++)
	{
		for (int j = 1; j <= l; j++) ss << o(maptest[i][j]);
		ss << std::endl;
	}
	std::string out = ss.str();
	system("cls");
	std::cout << out;
}
void findfood(int maptest[100][100], int& foodx, int& foody, int h, int l)//出食物
{
	for (;;)
	{
		srand((int)time(0));
		foodx = rand() % h + 1, foody = rand() % l + 1;
		if (maptest[foodx][foody] == 0) break;
	}
}
int gamein()
{
	int speed, h = 20, l = 30, tail = 6, maptest[100][100], x = h / 2, y = l / 2, tx = h / 2, ty = l / 2 - tail, foodx, foody, dir = 6, tdir = 6, food = 0;
	bool skip = 0;
	std::cout << "Speed (100-slow 50-medium 10-fast):" << std::endl;
	std::cin >> speed;
	Sleep(500);
	system("cls");
	for (int i = 1; i <= h; i++)//设置边界
	{
		for (int j = 1; j <= l; j++)
		{
			maptest[i][j] = 0;
			if (i == 1 || i == h) maptest[i][j] = 1;
		}
		maptest[i][1] = 1, maptest[i][l] = 1;
	}
	for (int i = ty + 1; i <= y; i++) maptest[x][i] = 6;
	findfood(maptest, foodx, foody, h, l);
	maptest[foodx][foody] = 3;
	drawmap(h, l, maptest);
	for (;;)
	{
		maptest[x][y] = dir;
		x = (dir == 2) ? (x + 1) : (dir == 8 ? x - 1 : x), y = (dir == 6) ? (y + 1) : (dir == 4 ? y - 1 : y);
		if (maptest[x][y] == 0 || maptest[x][y] == 3) maptest[x][y] = dir;
		else
		{
			std::cout << std::endl << "You died." << std::endl << "Score: " << food << std::endl << "Speed: " << speed << std::endl;
			std::cout << "0:exit" << std::endl;
			std::cout << "1:new game" << std::endl;
			char in1 = _getch();
			std::cout << std::endl;
			if (in1 == '0') return 0;
			else return gamein();
		}
		if (skip == 0)
			tx = (tdir == 2) ? (tx + 1) : (tdir == 8 ? tx - 1 : tx), ty = (tdir == 6) ? (ty + 1) : (tdir == 4 ? ty - 1 : ty), tdir = maptest[tx][ty];
		else skip = 0;
		maptest[tx][ty] = 0;
		drawmap(h, l, maptest);
		std::cout << "Score: " << food << std::endl << "Speed: " << speed << std::endl;
		Sleep(speed);
		if (_kbhit() != 0)
		{
			int in = _getch();
			if (in == 97 && dir != 4 && dir != 6) dir = 4;
			if (in == 115 && dir != 2 && dir != 8) dir = 2;
			if (in == 119 && dir != 2 && dir != 8) dir = 8;
			if (in == 100 && dir != 4 && dir != 6) dir = 6;
		}
		if (x == foodx && y == foody)
		{
			food++;
			findfood(maptest, foodx, foody, h, l);
			maptest[foodx][foody] = 3;
			skip = 1;
		}
	}
}
int main()
{
	return gamein();
}

图片