考虑:
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处的字符为偶数数字,则只应使用char。
实际上数学是相关的,因为它似乎强制$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中看到的相同......问题是什么?
答案 0 :(得分:1)
这里有几个问题。您的函数f()
可以写成:
fn digit2int(c: char): int = (c - '0')
fn f(): int = loop(example, 0, 0) where
{
fun
loop
{n:int}
{i:nat|i <= n}
(cs: string(n), i: int(i), acc: int): int =
if
string_is_atend(cs, i)
then acc else loop(cs, i+1, acc+digit2int(cs[i]))
}
这种编程涉及依赖类型。程序员经常要求更多。
答案 1 :(得分:1)
我尝试重新实现您的功能day2
:
fn digit2int(c: char): int = (c - '0')
fn
day2(input: string): int =
loop(0, 0) where
{
val n0 = strlen(input)
val n0 =
g0uint2int_size_int(n0)
val p0 = string2ptr(input)
fn nextindex(i: int): int = (i + n0/2) mod n0
fun get(i: int): char = $UNSAFE.ptr0_get_at<char>(p0, i)
fun loop(i: int, acc: int): int =
if i >= n0 then acc else
(
if get(i) = get(nextindex(i))
then loop(i+1, acc + digit2int(get(i))) else loop(i+1, acc)
)
}
我不得不说上面的实现非常难看(并且非常不安全)。如果我有时间,我会尽力在以后安全优雅地实施。
答案 2 :(得分:1)
好的,<OFX>
<SIGNONMSGSRQV1>
<SONRQ>
<DTCLIENT>20180108012004
<USERID>{Insert user id}
<USERPASS>{Insert password}
<LANGUAGE>ENG
<FI>
<ORG>B1 # Comes from ofxhome.com
<FID>10898
</FI>
<APPID>QWIN
<APPVER>1800
<CLIENTUID>{Insert random alphanumeric string}
</SONRQ>
</SIGNONMSGSRQV1>
<CREDITCARDMSGSRQV1>
<CCSTMTTRNRQ>
<TRNUID>{Insert random alphanumeric string}
<CLTCOOKIE>4
<CCSTMTRQ>
<CCACCTFROM>
<ACCTID>{Insert account id here}
</CCACCTFROM>
<INCTRAN>
<DTSTART>20171208
<INCLUDE>Y
</INCTRAN>
</CCSTMTRQ>
</CCSTMTTRNRQ>
</CREDITCARDMSGSRQV1>
</OFX>
的以下实现是安全的:
day2
答案 3 :(得分:0)
我能够在提供的帮助下完成这项工作,但只是为了有一个完整的功能示例,这是Day 1, 2017 Advent of Code的解决方案:
/* compile with: patscc -O2 -D_GNU_SOURCE -DATS_MEMALLOC_LIBC day1.dats -o day1 */
#include "share/atspre_staload.hats"
#include "share/atspre_staload_libats_ML.hats"
val input: string = "12341234" /* actual value provided by contest */
fn digit(c: char): uint =
case- c of
| '0' => 0u | '1' => 1u | '2' => 2u | '3' => 3u | '4' => 4u
| '5' => 5u | '6' => 6u | '7' => 7u | '8' => 8u | '9' => 9u
typedef charint = (char, uint)
fn part1(): uint = sum where {
val lastchar = input[strlen(input)-1]
val res = input.foldleft(TYPE{charint})((lastchar, 0u), (lam((last, sum): charint, c: char) =>
if last = c then (c, sum + digit(c)) else (c, sum)))
val sum = res.1
}
typedef natLT(n:int) = [i:nat | i < n] int(i)
typedef natLTe(n:int) = [i:nat | i <= n] int(i)
fn part2(): uint = loop(0, 0u) where {
val [n:int] input = g1ofg0(input)
val len = sz2i(strlen(input))
fn nextindex(i: natLT(n)): natLT(n) = nmod(i + len/2, len)
fun loop(i: natLTe(n), acc: uint): uint =
if i >= len then acc else
if input[i] = input[nextindex(i)] then loop(i+1, acc + digit(input[i])) else
loop(i+1, acc)
}
extern fun reset_timer(): void = "ext#reset_timer"
extern fun elapsed_time(): double = "ext#elapsed_time"
%{
#include <sys/time.h>
#include <time.h>
struct timeval timer_timeval;
void reset_timer() { gettimeofday(&timer_timeval, NULL); }
double elapsed_time() {
struct timeval now;
gettimeofday(&now, NULL);
int secs = now.tv_sec - timer_timeval.tv_sec;
double ms = (now.tv_usec - timer_timeval.tv_usec) / ((double)1000000);
return(secs + ms);
}
%}
fn bench(f: () -> void) = () where {
val () = reset_timer()
val () = f()
val c = elapsed_time()
val () = println!(" (timing: ", c, ")")
}
implement main0() =
begin
bench(lam() => print!("part1: ", part1()));
bench(lam() => print!("part2: ", part2()));
end
输出(假冒&#34; 12341234&#34;输入):
part1: 0 (timing: 0.000137)
part2: 20 (timing: 0.000001)