emacs识字编程 - 代码出现
#javascript #typescript #emacs #literateprogramming

目录

  1. First step
  2. The Problem
  3. Solution - Part 1
  4. Solution - Part 2
  5. Conclusion

识字编程是将自然语言相互融合到源代码而不是使用注释的一种很酷的方法。
它是由Donald Knuth侵入的。

emacs有一个有趣的方法来实现这一目标,除了配置emacs本身以外,我还没有真正看到它在其他任何地方使用,
因此,作为一个示例,让我们使用emacs org lentate编程来解决Advent of Code 2022 (Day 2),因为我选择的语言是打字稿。

我并不是很擅长打字稿,所以请记住,我的代码可能不会引起标准。

第一步

让我们创建一个名为“ day2.ts”的文件,然后初始化打字稿文件的必要配置,

npm init -y
tsc -init

创建一个使用“ .org”扩展名的文件,这将被识别为标准的emacs org doc,并在下面添加此行,

#+begin_src :tangle day2.ts 
  console.log("Hello Literate !"); 
#+end_src

使用“ alt-x”或“ c-c c-v t”调用命令“ org-babel-tangle”,当您打开“ day2.ts”文件时,您应该看到从org文件中写入的代码块。

如果一切顺利,那么我们将设置解决问题。

问题

问题的要点是,我们正在与精灵竞争岩石剪辑比赛中,

A -> Rock
B -> Paper
C -> Scissors

X -> Rock
Y -> Paper
Z -> Scissors 

比赛的点是根据您选择的形状来计算的

Rock -> 1
Paper -> 2
Scissors -> 3

and the outcome,

Draw -> 3
Lost -> 0
Win -> 6

解决方案 - 第1部分

让我们导入FS模块以读取“ input.txt”文件并将数据存储到变量中,

    import fs from "fs";

    const data = fs.readFileSync("./input.txt", "utf8").toString();

我们可以使用枚举来定义点和手,以及以后使用的模式匹配对象,

    enum HAND {
      X = "rock",
      Y = "paper",
      Z = "scissors",
      A = "rock",
      B = "paper",
      C = "scissors"
    }

    enum HAND_POINTS {
      rock = 1,
      paper = 2,
      scissors = 3
    }

    enum GAME_POINTS {
      WIN = 6,
      DRAW = 3,
      LOST = 0
    }

    const pattern = {
     "rock paper": "win",
     "paper scissors": "win",
     "scissors rock": "win",
     "scissors scissors": "draw",
     "paper paper": "draw",
     "rock rock": "draw",
     "paper rock": "lose",
     "scissors paper": "lose",
     "rock scissors": "lose",
    }

现在我们有了数据,让我们将字符串分为列表,

    const games = data.split("\n").map((str) => str.replace(/\r/g, "")).filter(Boolean);

Pointreturn功能进行单个游戏匹配并返回
指出球员获胜,

    function pointReturn(games: string[]): number {
      let counter = 0;
      for(const match of games){
        const game = match.split(" ");
        const opponentHand = HAND[game[0] as keyof typeof HAND];
        const playerHand = HAND[game[1] as keyof typeof HAND];
        const playerPoint = HAND_POINTS[playerHand as keyof typeof HAND_POINTS];
        const opponentPoint = HAND_POINTS[opponentHand as keyof typeof HAND_POINTS]
        const moveset: string = [opponentHand, playerHand].join(" ");

        if (pattern[moveset] == "win") {
          counter += GAME_POINTS.WIN + playerPoint;
        } else if (pattern[moveset] == "draw") {
          counter += GAME_POINTS.DRAW + playerPoint;
        } else if(pattern[moveset] == "lose") {
          counter += GAME_POINTS.LOST + playerPoint;
        }
       }

      return counter;
     }

最后,我们可以返回数据并记录它,

    const points = pointReturn(games);
    console.log(points)

解决方案 - 第2部分

在问题的第二部分中,我们需要确保我们输了并赢了
在仅特定的情况下。

如果“ x”然后输掉,“ y”绘制和“ z”是胜利,这确保了我们不
被发现为骗子。

以下功能获取输入数据并加入规则
更改播放器输入,即我们的数据转变为
的数据 达到策略。

    function strategizeInput(game: string[]){
      let newInput = [];
      for(const match of game){
        const [opponent, player] = match.split(" ");
        if(player == "X" && opponent == "A"){
         newInput.push([opponent, "Z"].join(" ")); 
        } else if(player == "X" && opponent == "B") {
          newInput.push([opponent, "X"].join(" ")); 
        } else if(player == "X" && opponent == "C") {
          newInput.push([opponent, "Y"].join(" "));
        }else if(player == "Y" && opponent == "A") {
          newInput.push([opponent, "X"].join(" "));
        } else if(player == "Y" && opponent == "B") {
          newInput.push([opponent, "Y"].join(" "));
        } else if(player == "Y" && opponent == "C") {
          newInput.push([opponent, "Z"].join(" "));
        } else if(player == "Z" && opponent == "A") {
          newInput.push([opponent, "Y"].join(" "));
        } else if(player == "Z" && opponent == "B") {
          newInput.push([opponent, "Z"].join(" "));
        } else if(player == "Z" && opponent == "C") {
          newInput.push([opponent, "X"].join(" "));
        }
      }

      return newInput;
    }

    console.log(pointReturn(strategizeInput(games)));

结论

emacs org babel是进行识字编程的有趣方式,尤其是
除了我不是
之外,要记录Emacs配置 非常确定如何使用它,而不是学习主题
在编写代码并同时记录您的Thougth时。

我在做这项练习时发现一些烦人的事情是
代码块通常没有“警告”来指示您是否
做错了什么,我不得不继续在
中恢复代码 “ day2.ts”文件,除此之外,这是一种非常有趣的方法
解决了这个问题,它使我能够在写作时更多地表达我的想法,而不是编码的感觉,感觉就像我在为别人学习的解释。

如果您在我的blog中查看它,这意味着整个文档是“问题”的实际源代码,而对于dev.to,我使用org在此处将org降低了emacs。

Github Repo