mem :: import "@std/mem" TaskList :: struct { ids ?[]mut i32 priorities ?[]mut i32 durations ?[]mut i32 len usize capacity usize allocator mem.Allocator } task_list_init func(allocator mem.Allocator) TaskList { return TaskList { ids = null, priorities = null, durations = null, len = 0, capacity = 0, allocator = allocator, } } alloc_i32s func(allocator mem.Allocator, count usize) ?[]mut i32 { fallback [1]mut i32 := undefined failed bool := false values []mut i32 := mem.alloc(allocator, count) catch |_| { failed = true yield (&fallback).ptr[..0] } if (failed) return null return values } free_i32s func(allocator mem.Allocator, values ?[]mut i32) void { if values |slice| { mem.free(allocator, slice) } } task_list_reserve func(list @mut TaskList, capacity usize) bool { if capacity <= list.capacity { return true } new_ids ?[]mut i32 := alloc_i32s(list.allocator, capacity) new_priorities ?[]mut i32 := alloc_i32s(list.allocator, capacity) new_durations ?[]mut i32 := alloc_i32s(list.allocator, capacity) if (new_ids and new_priorities and new_durations) |ids, priorities, durations| { if list.len > 0 { if (list.ids and list.priorities and list.durations) |old_ids, old_priorities, old_durations| { i usize := 0 while i < list.len : i += 1 { ids[i] = old_ids[i] priorities[i] = old_priorities[i] durations[i] = old_durations[i] } } else { free_i32s(list.allocator, new_ids) free_i32s(list.allocator, new_priorities) free_i32s(list.allocator, new_durations) return false } } free_i32s(list.allocator, list.ids) free_i32s(list.allocator, list.priorities) free_i32s(list.allocator, list.durations) list.ids = new_ids list.priorities = new_priorities list.durations = new_durations list.capacity = capacity return true } free_i32s(list.allocator, new_ids) free_i32s(list.allocator, new_priorities) free_i32s(list.allocator, new_durations) return false } task_list_push func(list @mut TaskList, id i32, priority i32, duration i32) bool { if list.len == list.capacity { new_capacity usize := 2 if list.capacity != 0 { new_capacity = list.capacity * 2 } if task_list_reserve(list, new_capacity) == false { return false } } if (list.ids and list.priorities and list.durations) |ids, priorities, durations| { index usize := list.len ids[index] = id priorities[index] = priority durations[index] = duration list.len += 1 return true } return false } task_score func(priority i32, duration i32) i32 { return priority * 10 - duration } task_list_best_id func(list @mut TaskList) i32 { if list.len == 0 { return -1 } if (list.ids and list.priorities and list.durations) |ids, priorities, durations| { best_index usize := 0 best_score i32 := task_score(priorities[0], durations[0]) i usize := 1 while i < list.len : i += 1 { score i32 := task_score(priorities[i], durations[i]) if score > best_score { best_score = score best_index = i } } return ids[best_index] } return -1 } task_list_total_duration func(list @mut TaskList) i32 { total i32 := 0 if list.durations |durations| { i usize := 0 while i < list.len : i += 1 { total += durations[i] } } return total } task_list_deinit func(list @mut TaskList) void { free_i32s(list.allocator, list.ids) free_i32s(list.allocator, list.priorities) free_i32s(list.allocator, list.durations) list.ids = null list.priorities = null list.durations = null list.len = 0 list.capacity = 0 } task_list_test func() i32 { tasks TaskList := task_list_init(mem.c_allocator) defer task_list_deinit(&tasks) if task_list_push(&tasks, 101, 3, 5) == false { return 5 } if tasks.capacity != 2 { return 6 } if task_list_push(&tasks, 202, 1, 4) == false { return 7 } if tasks.capacity != 2 { return 8 } if task_list_push(&tasks, 303, 4, 8) == false { return 9 } if tasks.capacity != 4 { return 10 } if tasks.len != 3 { return 11 } if task_list_best_id(&tasks) != 303 { return 12 } if task_list_total_duration(&tasks) != 17 { return 13 } return 0 }