C* Online Judge

Singly Linked List Sum / 单链表求和

180s · 1024 MiB memory · 256 MiB scratch

Judge: stonebuddha/cstar@sha256:5dcb310423703ae4ee37e7334802f6bb7f8af079e6e3291b5ee9f0be44c6ccf8 · linux/amd64

Singly Linked List Sum / 单链表求和

English

Given the head pointer p of a singly linked list, prove that the supplied function sll_sum(p) returns the sum of all node values and preserves the list's values and links. Each node has this layout:

struct list {
  int data;
  struct list *next;
};

The input is a finite, acyclic, null-terminated list satisfying:

The function starts with a sum of zero, adds p->data, and advances to p->next until the pointer is null. The empty list (p == NULL) returns 0. All specification sums use mathematical integers. The prefix bounds ensure that each addition fits in a signed 32-bit int; a bound on the final sum alone would not be sufficient.

The supplied problem.h contains the node declaration and the mathematical list model used by the contract:

Symbol Meaning
sll p input Ownership of the whole list and its node values
sllseg p q values Segment ownership ending before q, used to define sll
list_sum input Mathematical sum of the values, with empty sum 0

The header initializes these definitions automatically. The ghost list input records the original values; the postcondition requires the result to equal list_sum input and restores sll at the original head pointer.

Define any auxiliary predicates and prove the lemmas needed for your invariants in starter.c; the header supplies only the contract model and its dependencies.

The implementation and contract are fixed. Add loop invariants and proof code only inside starter.c; changing the implementation or specification is rejected by the judge and consumes an attempt. Submit the completed starter.c. No main function, input/output code, or list allocation is needed.

中文

给定单链表头指针 p,请证明给定函数 sll_sum(p) 返回所有节点值之和,并保持链表节点值和链接结构不变。节点结构如下:

struct list {
  int data;
  struct list *next;
};

输入是有限、无环、以空指针结尾的单链表,并满足:

函数从 0 开始累加,每次加上 p->data,再沿 p->next 前进,直到指针为空。空链表(p == NULL)返回 0。规约中的求和使用数学整数;前缀和约束保证每次加法均在 32 位有符号 int 的范围内。仅保证最终总和不溢出是不够的。

给定的 problem.h 已包含节点定义以及规约使用的链表模型:

符号 含义
sll p input 整条链表的内存所有权及节点值
sllseg p q values 用于定义 sll 的链表段,从 p 开始、在 q 之前结束
list_sum input 节点值的数学整数和,空列表的和为 0

头文件会自动初始化这些固定定义。幽灵列表 input 记录原始节点值;后置条件要求返回值等于 list_sum input,并在原始头指针处恢复 sll 断言。

请在 starter.c 中自行定义不变式所需的辅助谓词并证明所需引理;头文件仅提供规约模型及其依赖定义。

实现和契约均为固定内容。你只能在 starter.c 中添加循环不变式和证明代码;修改实现或规约将被判定为失败,并消耗一次提交机会。提交完成后的 starter.c 即可,不需要编写 main 函数、输入输出代码或链表分配代码。

Examples / 示例

Node values from head to tail / 从头到尾的节点值 Return value / 返回值
[] 0
[-100000] -100000
[1, 2, 3, 4] 10
[100000, -100000, 7, -2] 5
[-3, -4, -5] -12