【发布时间】:2018-01-08 05:09:24
【问题描述】:
考虑:
val example = "1234567"
fn digit(c: char): int =
case- c of
| '0' => 0 | '1' => 1 | '2' => 2 | '3' => 3 | '4' => 4
| '5' => 5 | '6' => 6 | '7' => 7 | '8' => 8 | '9' => 9
fn f(): int = loop(0, 0) where {
fun loop(i: int, acc: int): int =
if example[i] = '\000' then acc else
loop(i + 1, acc + digit(example[i]))
}
implement main0() = () where {
val () = println!("f: ", f())
}
这(尝试)循环遍历字符串的索引,将字符串的字符求和为数字。我已经用.foldleft 和streamize_string_char 解决了几个类似的问题,但实际任务需要对索引本身进行数学运算(即,不是使用每个字符,它应该只使用一个字符,如果i+10 处的字符为偶数)。
实际上数学是相关的,因为它似乎强制$UNSAFE.cast2int,因为strlen(input)的结果没有除法运算符:
fn day2(): uint = loop(input, 0, 0) where {
val len = $UNSAFE.cast2int(strlen(input))
fn nextindex(i: int): int = (i + len/2) mod len
fn get(i: int): char = input[i] // <-- also broken at this point
// this next line is just me slowly going mad
fun loop{n:int}{i:nat | i <= n}(s: string(n), i: size_t(i), acc: uint): uint =
if i >= len then acc else
if s[i] = s[nextindex(i)] then loop(i+1, acc + digit(s[i])) else
loop(i+1, acc)
}
f()上面应该怎么写?请给我一个函数示例,该函数循环遍历字符串的索引并按索引从字符串中获取字符。同样,我不需要像
typedef charint = (char, int)
fn day1(): int = sum where {
val lastchar = input[strlen(input)-1]
val res = input.foldleft(TYPE{charint})((lastchar, 0), (lam((last, sum): charint, c: char) =>
if last = c then (c, sum + digit(c)) else (c, sum)))
val sum = res.1
}
因为我需要根据索引测试属性。
编辑:
好吧,我终于想出了一些种解决方案,但看看它有多荒谬。必须有正确和适当的 ATS 方式来执行此操作。
#include "share/atspre_staload.hats"
val example = "1234567"
fn digit(c: char): int =
case- c of
| '0' => 0 | '1' => 1 | '2' => 2 | '3' => 3 | '4' => 4
| '5' => 5 | '6' => 6 | '7' => 7 | '8' => 8 | '9' => 9
fn f(): int = loop(0, 0) where {
fn get(i: int): char = loop(i, string2ptr(example)) where {
fun loop(i: int, s: ptr): char =
if i > 0 then loop(i-1, ptr0_succ<char>(s)) else
$UNSAFE.ptr0_get<char>(s)
}
fun loop(i: int, acc: int): int =
if get(i) = '\000' then acc else
loop(i + 1, acc + digit(get(i)))
}
implement main0() = () where {
val () = println!("f: ", f())
}
输出:
f: 28
EDIT2:
不那么荒谬:
...
val p = string2ptr(example)
fn get(i: int): char = $UNSAFE.ptr0_get<char>(add_ptr_bsz(p, g0int2uint(i) * sizeof<char>))
...
EDIT3:
我可以再次使用string[i]
overload + with add_ptr_bsz
fn string_get_at(str, i) = $UNSAFE.ptr0_get<charNZ>(string2ptr(str)+g0int2uint(i))
overload [] with string_get_at
这与我在 prelude/DATS/string.dats 中看到的几乎相同......有什么问题?
【问题讨论】:
-
已批准编辑,但我怀疑提高可见性是否会带来任何好处。如果您不了解 ATS,就无法回答这个问题。