代码挑战的OCaml实现

代码挑战的OCaml实现,ocaml,ocaml-core,Ocaml,Ocaml Core,我正在做一个每日代码挑战,允许使用任何语言。我最近一直在使用真实世界的OCaml。我真的很想知道如何用惯用的OCaml解决这个特殊的挑战。下面是我的两个JavaScript实现。挑战在于识别数学金字塔中的模式: 一, 11 21 1211 111221 (模式为一个1、两个1、一个2、一个1、三个1、两个2、一个1,从下一个“级别”或行读取的数字) 函数createNextLevel(上一级,当前级=0,最终级=40){ 让sub=''; 设level=''; //在字符串上迭代 for(设i=

我正在做一个每日代码挑战,允许使用任何语言。我最近一直在使用真实世界的OCaml。我真的很想知道如何用惯用的OCaml解决这个特殊的挑战。下面是我的两个JavaScript实现。挑战在于识别数学金字塔中的模式:

一, 11 21 1211 111221

(模式为一个1、两个1、一个2、一个1、三个1、两个2、一个1,从下一个“级别”或行读取的数字)

函数createNextLevel(上一级,当前级=0,最终级=40){
让sub='';
设level='';
//在字符串上迭代
for(设i=0;i{
级别+=`${String(group.length)}${group[0]}`;
});
控制台日志(级别);
如果(当前级别<最终级别){
createNextLevelPlus(级别,当前级别+1)
}
}
var firstLevel='1';
createNextLevelPlus(第一级);

我曾经思考过如何在OCaml中解决这个问题,但我确信我只是在重新发明一种基于C的方法。我考虑过递归地遍历字符串并在头和尾上匹配。。。看看它们是否相等,并将结果存储在某种元组或其他东西中。。。我很难将我的思想扭曲到正确的思维中。

这里有一个高级分解

您需要迭代函数的东西。有一个循环+显示部分和一个迭代部分(如何从一个级别转到下一个级别)

每个迭代中有两个步骤:

  • 数一数连续的数字(将1211变为“一、一、二、二个一”)
  • 将计数列表转换为列表(将“一、一、二、二个一”转换为111221)
现在,让我们考虑一下类型。我们从不将这些数字用作数字(没有加法等),因此它们可以被视为整数列表,或者在OCaml
int list

另一方面,计数也是一个列表,但列表中的每个元素都是一对(计数,值)。例如,“一个一个二个一”可以表示为
[(1,1);(1,2);(2,1)]
。OCaml中此类内容的类型是
(int*int)list

换句话说,算法的重要部分是:

  • 一种类型为
    int list->(int*int)list
    的函数,用于对连续元素进行计数
  • 类型为
    (int*int)list->int list
    的函数,用于将这些计数转换为新列表

一旦你有了这些,你应该能够把这些碎片放在一起。玩得开心

这是一个高级分解

您需要迭代函数的东西。有一个循环+显示部分和一个迭代部分(如何从一个级别转到下一个级别)

每个迭代中有两个步骤:

  • 数一数连续的数字(将1211变为“一、一、二、二个一”)
  • 将计数列表转换为列表(将“一、一、二、二个一”转换为111221)
现在,让我们考虑一下类型。我们从不将这些数字用作数字(没有加法等),因此它们可以被视为整数列表,或者在OCaml
int list

另一方面,计数也是一个列表,但列表中的每个元素都是一对(计数,值)。例如,“一个一个二个一”可以表示为
[(1,1);(1,2);(2,1)]
。OCaml中此类内容的类型是
(int*int)list

换句话说,算法的重要部分是:

  • 一种类型为
    int list->(int*int)list
    的函数,用于对连续元素进行计数
  • 类型为
    (int*int)list->int list
    的函数,用于将这些计数转换为新列表

一旦你有了这些,你应该能够把这些碎片放在一起。玩得开心

哇,谢谢你!这正是我要找的东西。很高兴能帮上忙!如果您希望在编写代码后对其进行一些审阅,如果您需要一些输入,请随时发布。哇,谢谢!这正是我要找的东西。很高兴能帮上忙!如果您希望在编写代码后对其进行一些检查,如果您需要一些输入,请随时发布。
function createNextLevel(previousLevel, currentLevel = 0, finalLevel = 40) {
    let sub = '';
    let level = '';
    // iterate on string
    for (let i = 0; i < previousLevel.length; i++) {
        // if we don't have an element to the left or it's  equal to current element
        if (!previousLevel[i - 1] || previousLevel[i] === previousLevel[i - 1]) {
            sub += previousLevel[i]; // sub '2'
        } else {
            level += String(sub.length) + sub[0]; // ''
            sub = previousLevel[i];
        }

        // if we're at the end
        if (i === previousLevel.length - 1) {
            level += String(sub.length) + sub[0]; // '21'
        }
    }

    console.log(level);

    if (currentLevel < finalLevel) {
        createNextLevel(level, currentLevel + 1)
    }
}

var firstLevel = '1';
createNextLevel(firstLevel);

// A bit simpler approach
function createNextLevelPlus(str, currentLevel = 0, finalLevel = 10) {
    var delimitedStr = '';
    var level = '';

    for (let i = 0; i < str.length; i++) {
        if (!str[i + 1] || str[i] === str[i+1]) {
            delimitedStr += str[i];
        } else {
            delimitedStr += str[i] + '|';
        }
    }

    delimitedStr.split('|').forEach((group, idx, arr) => {
        level += `${String(group.length)}${group[0]}`;
    });

    console.log(level);

    if (currentLevel < finalLevel) {
        createNextLevelPlus(level, currentLevel+1)
    }
}

var firstLevel = '1';
createNextLevelPlus(firstLevel);