String 如何循环字符串的索引?

String 如何循环字符串的索引?,string,loops,indexing,ats,String,Loops,Indexing,Ats,考虑: 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

考虑:

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处的字符是偶数数字,它应该只使用一个字符,而不是使用每个字符)

实际上,数学是相关的,因为它似乎强制
$safe.cast2int
,因为
strlen(input)
的结果没有除法运算符:

因为我需要基于索引测试属性

编辑:

我终于想出了一些解决办法,但看看这有多荒谬。必须有一个正确的方法来做到这一点

#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())
}
编辑2:

不那么荒谬:

...
  val p = string2ptr(example)
  fn get(i: int): char = $UNSAFE.ptr0_get<char>(add_ptr_bsz(p, g0int2uint(i) * sizeof<char>))
...

这与我在prelude/DATS/string.DATS中看到的几乎相同。。。有什么问题吗?

这里有几个问题。函数
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]))
}
fn digit2int(c:char):int=(c-“0”)
fn f():int=loop(例如,0,0),其中
{
享乐
环
{n:int}

{i:nat | i这里有几个问题。您的函数
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]))
}
fn digit2int(c:char):int=(c-“0”)
fn f():int=loop(例如,0,0),其中
{
享乐
环
{n:int}

{i:nat | i我尝试重新实现您的函数
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)
    )
}
fn digit2int(c:char):int=(c-“0”)
fn
第2天(输入:字符串):int=
循环(0,0),其中
{
val n0=strlen(输入)
瓦尔n0=
g0uint2int\u大小\u int(n0)
val p0=string2ptr(输入)
fn nextindex(i:int):int=(i+n0/2)mod n0
fun get(i:int):char=$safe.ptr0_get_at(p0,i)
有趣的循环(i:int,acc:int):int=
如果i>=n0,则acc else
(
如果get(i)=get(nextindex(i))
然后循环(i+1,acc+digit2int(get(i)),否则循环(i+1,acc)
)
}

我不得不说,上面的实现非常难看(而且风格非常不安全)。如果我有时间,我将尝试稍后提供一个安全而优雅的实现。

我尝试重新实现您的功能
第2天

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)
    )
}
fn digit2int(c:char):int=(c-“0”)
fn
第2天(输入:字符串):int=
循环(0,0),其中
{
val n0=strlen(输入)
瓦尔n0=
g0uint2int\u大小\u int(n0)
val p0=string2ptr(输入)
fn nextindex(i:int):int=(i+n0/2)mod n0
fun get(i:int):char=$safe.ptr0_get_at(p0,i)
有趣的循环(i:int,acc:int):int=
如果i>=n0,则acc else
(
如果get(i)=get(nextindex(i))
然后循环(i+1,acc+digit2int(get(i)),否则循环(i+1,acc)
)
}

我不得不说,上面的实现非常难看(而且风格非常不安全)。如果我有时间,我将尝试稍后提供一个安全而优雅的实现。

好的,下面的
day2
实现是安全的:

fn
day2
(input: string): uint = let

val
[n:int]
input = g1ofg0(input)

val n0 = strlen(input)
val n0 = sz2i(n0) // int(n)

fun
nextindex
(
 i: natLt(n)
) : natLt(n) = nmod(i + n0/2, n0)

fun
loop(i: natLte(n), acc: uint): uint =
  if i >= n0 then acc else
  (
    if input[i] = input[nextindex(i)]
      then loop(i+1, acc + digit2uint(input[i]))
      else loop(i+1, acc)
  )

in
  loop(0, 0u)
end // end of [day2]

好的,
day2
的以下实现是安全的:

fn
day2
(input: string): uint = let

val
[n:int]
input = g1ofg0(input)

val n0 = strlen(input)
val n0 = sz2i(n0) // int(n)

fun
nextindex
(
 i: natLt(n)
) : natLt(n) = nmod(i + n0/2, n0)

fun
loop(i: natLte(n), acc: uint): uint =
  if i >= n0 then acc else
  (
    if input[i] = input[nextindex(i)]
      then loop(i+1, acc + digit2uint(input[i]))
      else loop(i+1, acc)
  )

in
  loop(0, 0u)
end // end of [day2]

在提供的帮助下,我能够完成这项工作,但也有一个完整的功能示例,下面是一个解决方案:


在提供的帮助下,我能够完成这项工作,但也有一个完整的功能示例,下面是一个解决方案:


已批准的编辑,但我怀疑增加可见性是否会带来任何好处。如果您不了解ATS,则无法回答此问题。已批准的编辑,但我怀疑增加可见性是否会带来任何好处。如果您不了解ATS,则无法回答此问题。
fn
day2
(input: string): uint = let

val
[n:int]
input = g1ofg0(input)

val n0 = strlen(input)
val n0 = sz2i(n0) // int(n)

fun
nextindex
(
 i: natLt(n)
) : natLt(n) = nmod(i + n0/2, n0)

fun
loop(i: natLte(n), acc: uint): uint =
  if i >= n0 then acc else
  (
    if input[i] = input[nextindex(i)]
      then loop(i+1, acc + digit2uint(input[i]))
      else loop(i+1, acc)
  )

in
  loop(0, 0u)
end // end of [day2]
/* 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
part1: 0 (timing: 0.000137)
part2: 20 (timing: 0.000001)