Compare commits
15 Commits
7b032a1ef4
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 7a37e28de1 | |||
| 78efe71bc0 | |||
| d72b651818 | |||
| 51ce912081 | |||
| 77f92130bf | |||
| b5fb1445fd | |||
| 0a5969b2e0 | |||
| c1a5ce4494 | |||
| 55705a796a | |||
| aa176f7038 | |||
| aa20952dc2 | |||
| 002fff8d1d | |||
| 0d7a0f9986 | |||
| 649de7b871 | |||
| cbc9db76f2 |
31
src/Go/003.go
Normal file
31
src/Go/003.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
)
|
||||
|
||||
var ORDER = []string{"R", "A", "M"}
|
||||
|
||||
func tricolor_flag(lst []string) []string {
|
||||
result := append([]string(nil), lst...) // copy (like Python sorted)
|
||||
order := make(map[string]int, len(ORDER))
|
||||
for i, v := range ORDER {
|
||||
order[v] = i
|
||||
}
|
||||
|
||||
sort.SliceStable(result, func(i int, j int) bool {
|
||||
return order[result[i]] < order[result[j]]
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
}
|
||||
|
||||
func main() {
|
||||
check := []string{"M","R","A","A","R","R","A","M","M"}
|
||||
fmt.Println(tricolor_flag(check)) // [R,R,R,A,A,A,M,M,M]
|
||||
|
||||
check = []string{"M", "R", "A", "R", "R", "A"}
|
||||
fmt.Println(tricolor_flag(check)) // [R,R,R,A,A,M]
|
||||
}
|
||||
70
src/Go/004.go
Normal file
70
src/Go/004.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func toSet(values []int) map[int]struct{} {
|
||||
set := make(map[int]struct{}, len(values))
|
||||
for _, value := range values {
|
||||
set[value] = struct{}{}
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
func isSubset(left map[int]struct{}, right map[int]struct{}) bool {
|
||||
for value := range left {
|
||||
if _, ok := right[value]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func minimales(values [][]int) [][]int {
|
||||
res := [][]int{}
|
||||
|
||||
for index, candidate := range values {
|
||||
candidateSet := toSet(candidate)
|
||||
|
||||
isSubsetOfAnother := false
|
||||
for otherIndex, other := range values {
|
||||
if index == otherIndex {
|
||||
continue
|
||||
}
|
||||
|
||||
otherSet := toSet(other)
|
||||
if isSubset(candidateSet, otherSet) {
|
||||
isSubsetOfAnother = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if isSubsetOfAnother {
|
||||
continue
|
||||
}
|
||||
|
||||
alreadyPresent := false
|
||||
for _, existing := range res {
|
||||
existingSet := toSet(existing)
|
||||
if len(candidateSet) == len(existingSet) &&
|
||||
isSubset(candidateSet, existingSet) {
|
||||
alreadyPresent = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !alreadyPresent {
|
||||
res = append(res, candidate)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func main() {
|
||||
check := [][]int{[]int{1, 3}, []int{2, 3, 1}, []int{3, 2, 5}}
|
||||
fmt.Println(minimales(check)) // [[2, 3, 1], [3, 2, 5]]
|
||||
|
||||
check = [][]int{[]int{1, 3}, []int{2, 3, 1}, []int{3, 2, 5}, []int{3, 1}}
|
||||
fmt.Println(minimales(check)) // [[2, 3, 1], [3, 2, 5]]
|
||||
}
|
||||
57
src/Go/005.go
Normal file
57
src/Go/005.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func mastermind(lst_1 []int, lst_2 []int) (int, int) {
|
||||
indexMatch := 0
|
||||
valueMatch := 0
|
||||
|
||||
for idx, element := range lst_1 {
|
||||
if lst_1[idx] == lst_2[idx] {
|
||||
indexMatch++
|
||||
continue
|
||||
}
|
||||
found := false
|
||||
for _, value := range lst_2 {
|
||||
if element == value {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if found {
|
||||
valueMatch++
|
||||
}
|
||||
}
|
||||
|
||||
return indexMatch, valueMatch
|
||||
}
|
||||
|
||||
func main() {
|
||||
{
|
||||
check_1 := []int{2, 6, 0, 7}
|
||||
check_2 := []int{1, 4, 0, 6}
|
||||
result_1, result_2 := mastermind(check_1, check_2)
|
||||
fmt.Println(result_1, result_2) // (1, 1)
|
||||
}
|
||||
|
||||
{
|
||||
check_1 := []int{2, 6, 0, 7}
|
||||
check_2 := []int{3, 5, 9, 1}
|
||||
result_1, result_2 := mastermind(check_1, check_2)
|
||||
fmt.Println(result_1, result_2) // (0, 0)
|
||||
}
|
||||
|
||||
{
|
||||
check_1 := []int{2, 6, 0, 7}
|
||||
check_2 := []int{1, 6, 0, 4}
|
||||
result_1, result_2 := mastermind(check_1, check_2)
|
||||
fmt.Println(result_1, result_2) // (2, 0)
|
||||
}
|
||||
|
||||
{
|
||||
check_1 := []int{2, 6, 0, 7}
|
||||
check_2 := []int{2, 6, 0, 7}
|
||||
result_1, result_2 := mastermind(check_1, check_2)
|
||||
fmt.Println(result_1, result_2) // (4, 0)
|
||||
}
|
||||
}
|
||||
13
src/Julia/003.jl
Normal file
13
src/Julia/003.jl
Normal file
@@ -0,0 +1,13 @@
|
||||
ORDER = ("R", "A", "M")
|
||||
|
||||
function tricolor_flag(lst)
|
||||
order = Dict(value => idx for (idx, value) in enumerate(ORDER))
|
||||
return sort(lst, by= x -> order[x])
|
||||
end
|
||||
|
||||
|
||||
check = ["M","R","A","A","R","R","A","M","M"]
|
||||
println(tricolor_flag(check)) # [R,R,R,A,A,A,M,M,M]
|
||||
|
||||
check = ["M", "R", "A", "R", "R", "A"]
|
||||
println(tricolor_flag(check)) # [R,R,R,A,A,M]
|
||||
27
src/Julia/004.jl
Normal file
27
src/Julia/004.jl
Normal file
@@ -0,0 +1,27 @@
|
||||
function minimales(lst)
|
||||
res = Vector{Vector{Int}}()
|
||||
for (index, canditate) in enumerate(lst)
|
||||
canditate_set = Set(canditate)
|
||||
|
||||
is_subset_of_another = any(
|
||||
index != other_index && canditate_set <= Set(other)
|
||||
for (other_index, other) in enumerate(lst)
|
||||
)
|
||||
|
||||
if is_subset_of_another
|
||||
continue
|
||||
end
|
||||
|
||||
if !any(canditate_set == Set(existing) for existing in res)
|
||||
push!(res, canditate)
|
||||
end
|
||||
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
check = [[1, 3], [2, 3, 1], [3, 2, 5]]
|
||||
println(minimales(check)) # [[2, 3, 1], [3, 2, 5]]
|
||||
|
||||
check = [[1, 3], [2, 3, 1], [3, 2, 5], [3, 1]]
|
||||
println(minimales(check)) # [[2, 3, 1], [3, 2, 5]]
|
||||
30
src/Julia/005.jl
Normal file
30
src/Julia/005.jl
Normal file
@@ -0,0 +1,30 @@
|
||||
function mastermind(lst_1, lst_2)
|
||||
index_match = 0
|
||||
match = 0
|
||||
for (idx, element) in enumerate(lst_1)
|
||||
if lst_1[idx] == lst_2[idx]
|
||||
index_match += 1
|
||||
continue
|
||||
end
|
||||
if element in lst_2
|
||||
match += 1
|
||||
end
|
||||
end
|
||||
return (index_match, match)
|
||||
end
|
||||
|
||||
check_1 = [2, 6, 0, 7]
|
||||
check_2 = [1, 4, 0, 6]
|
||||
println(mastermind(check_1, check_2)) # (1, 1)
|
||||
|
||||
check_1 = [2, 6, 0, 7]
|
||||
check_2 = [3, 5, 9, 1]
|
||||
println(mastermind(check_1, check_2)) # (0, 0)
|
||||
|
||||
check_1 = [2, 6, 0, 7]
|
||||
check_2 = [1, 6, 0, 4]
|
||||
println(mastermind(check_1, check_2)) # (2, 0)
|
||||
|
||||
check_1 = [2, 6, 0, 7]
|
||||
check_2 = [2, 6, 0, 7]
|
||||
println(mastermind(check_1, check_2)) # (4, 0)
|
||||
11
src/Python/003.py
Normal file
11
src/Python/003.py
Normal file
@@ -0,0 +1,11 @@
|
||||
ORDER = ("R", "A", "M")
|
||||
|
||||
def tricolor_flag(lst: list) -> list:
|
||||
order: dict[str, int] = {value: idx for idx, value in enumerate(ORDER)}
|
||||
return sorted(lst, key=order.__getitem__)
|
||||
|
||||
check = ["M","R","A","A","R","R","A","M","M"]
|
||||
print(tricolor_flag(check)) # [R,R,R,A,A,A,M,M,M]
|
||||
|
||||
check = ["M", "R", "A", "R", "R", "A"]
|
||||
print(tricolor_flag(check)) # [R,R,R,A,A,M]
|
||||
22
src/Python/004.py
Normal file
22
src/Python/004.py
Normal file
@@ -0,0 +1,22 @@
|
||||
def minimales(lst: list[list[int]]) -> list[list[int]]:
|
||||
res = []
|
||||
for index, candidate in enumerate(lst):
|
||||
candidate_set = set(candidate)
|
||||
|
||||
is_subset_of_another = any(
|
||||
index != other_index and candidate_set <= set(other)
|
||||
for other_index, other in enumerate(lst)
|
||||
)
|
||||
if is_subset_of_another:
|
||||
continue
|
||||
|
||||
if not any(candidate_set == set(existing) for existing in res):
|
||||
res.append(candidate)
|
||||
|
||||
return res
|
||||
|
||||
check = [[1, 3], [2, 3, 1], [3, 2, 5]]
|
||||
print(minimales(check)) # [[2, 3, 1], [3, 2, 5]]
|
||||
|
||||
check = [[1, 3], [2, 3, 1], [3, 2, 5], [3, 1]]
|
||||
print(minimales(check)) # [[2, 3, 1], [3, 2, 5]]
|
||||
26
src/Python/005.py
Normal file
26
src/Python/005.py
Normal file
@@ -0,0 +1,26 @@
|
||||
def mastermind(lst_1: list[int], lst_2: list[int]) -> tuple[int, int]:
|
||||
match = 0
|
||||
index_match = 0
|
||||
for idx, element in enumerate(lst_1):
|
||||
if lst_1[idx] == lst_2[idx]:
|
||||
index_match += 1
|
||||
continue
|
||||
if element in lst_2:
|
||||
match += 1
|
||||
return (index_match, match)
|
||||
|
||||
check_1 = [2, 6, 0, 7]
|
||||
check_2 = [1, 4, 0, 6]
|
||||
print(mastermind(check_1, check_2)) # (1, 1)
|
||||
|
||||
check_1 = [2, 6, 0, 7]
|
||||
check_2 = [3, 5, 9, 1]
|
||||
print(mastermind(check_1, check_2)) # (0, 0)
|
||||
|
||||
check_1 = [2, 6, 0, 7]
|
||||
check_2 = [1, 6, 0, 4]
|
||||
print(mastermind(check_1, check_2)) # (2, 0)
|
||||
|
||||
check_1 = [2, 6, 0, 7]
|
||||
check_2 = [2, 6, 0, 7]
|
||||
print(mastermind(check_1, check_2)) # (4, 0)
|
||||
BIN
src/Rust/001
BIN
src/Rust/001
Binary file not shown.
20
src/Rust/003.rs
Normal file
20
src/Rust/003.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
const ORDER: [&str; 3] = ["R", "A", "M"];
|
||||
|
||||
fn tricolor_flag<'a>(lst: &[&'a str]) -> Vec<&'a str> {
|
||||
let mut ordered_lst = lst.to_vec();
|
||||
ordered_lst.sort_by_key(|s| {
|
||||
ORDER
|
||||
.iter()
|
||||
.position(|&v| v == *s)
|
||||
});
|
||||
|
||||
return ordered_lst
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let check = vec!["M","R","A","A","R","R","A","M","M"];
|
||||
println!("{:?}", tricolor_flag(&check)); // [R,R,R,A,A,A,M,M,M]
|
||||
|
||||
let check = vec!["M", "R", "A", "R", "R", "A"];
|
||||
println!("{:?}", tricolor_flag(&check)); // [R,R,R,A,A,M]
|
||||
}
|
||||
57
src/Rust/004.rs
Normal file
57
src/Rust/004.rs
Normal file
@@ -0,0 +1,57 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
fn minimales(values: &[Vec<i32>]) -> Vec<Vec<i32>> {
|
||||
let mut res: Vec<Vec<i32>> = Vec::new();
|
||||
|
||||
for (index, candidate) in values.iter().enumerate() {
|
||||
let candidate_set: HashSet<i32> = candidate.iter().copied().collect();
|
||||
|
||||
// let mut is_subset_of_another = false;
|
||||
|
||||
// for (other_index, other) in values.iter().enumerate() {
|
||||
// let result = if index == other_index {
|
||||
// false
|
||||
// } else {
|
||||
// let other_set: HashSet<i32> = other.iter().copied().collect();
|
||||
// candidate_set.is_subset(&other_set)
|
||||
// };
|
||||
|
||||
// if result {
|
||||
// is_subset_of_another = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
let is_subset_of_another = values.iter().enumerate().any(|(other_index, other)| {
|
||||
if index == other_index {
|
||||
return false;
|
||||
}
|
||||
|
||||
let other_set: HashSet<i32> = other.iter().copied().collect();
|
||||
candidate_set.is_subset(&other_set)
|
||||
});
|
||||
|
||||
if is_subset_of_another {
|
||||
continue;
|
||||
}
|
||||
|
||||
let already_present = res.iter().any(|existing| {
|
||||
let existing_set: HashSet<i32> = existing.iter().copied().collect();
|
||||
candidate_set == existing_set
|
||||
});
|
||||
|
||||
if !already_present {
|
||||
res.push(candidate.clone());
|
||||
}
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let check = vec![vec![1, 3], vec![2, 3, 1], vec![3, 2, 5]];
|
||||
println!("{:?}", minimales(&check)); // [[2, 3, 1], [3, 2, 5]]
|
||||
|
||||
let check = vec![vec![1, 3], vec![2, 3, 1], vec![3, 2, 5], vec![3, 1]];
|
||||
println!("{:?}", minimales(&check)); // [[2, 3, 1], [3, 2, 5]]
|
||||
}
|
||||
34
src/Rust/005.rs
Normal file
34
src/Rust/005.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
fn mastermind(lst_1: &[i32], lst_2: &[i32]) -> (i32, i32) {
|
||||
let mut index_match: i32 = 0;
|
||||
let mut match_value: i32 = 0;
|
||||
|
||||
for idx in 0..lst_1.len() {
|
||||
if lst_1[idx] == lst_2[idx] {
|
||||
index_match += 1;
|
||||
continue;
|
||||
}
|
||||
if lst_2.contains(&lst_1[idx]) {
|
||||
match_value += 1;
|
||||
}
|
||||
}
|
||||
|
||||
(index_match, match_value)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let check_1 = vec![2, 6, 0, 7];
|
||||
let check_2 = vec![1, 4, 0, 6];
|
||||
println!("{:?}", mastermind(&check_1, &check_2)); // (1, 1)
|
||||
|
||||
let check_1 = vec![2, 6, 0, 7];
|
||||
let check_2 = vec![3, 5, 9, 1];
|
||||
println!("{:?}", mastermind(&check_1, &check_2)); // (0, 0)
|
||||
|
||||
let check_1 = vec![2, 6, 0, 7];
|
||||
let check_2 = vec![1, 6, 0, 4];
|
||||
println!("{:?}", mastermind(&check_1, &check_2)); // (2, 0)
|
||||
|
||||
let check_1 = vec![2, 6, 0, 7];
|
||||
let check_2 = vec![2, 6, 0, 7];
|
||||
println!("{:?}", mastermind(&check_1, &check_2)); // (4, 0)
|
||||
}
|
||||
506
src/template.py
Normal file
506
src/template.py
Normal file
@@ -0,0 +1,506 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Creation of templates for Exercitium problems
|
||||
"""
|
||||
|
||||
import ast
|
||||
import re
|
||||
from argparse import ArgumentParser
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Example:
|
||||
input_values: tuple[object, ...]
|
||||
expected_value: object
|
||||
|
||||
|
||||
def load_instructions(path: Path) -> str:
|
||||
return path.read_text(encoding="utf-8").strip()
|
||||
|
||||
def split_top_level_values(text: str) -> list[str]:
|
||||
parts: list[str] = []
|
||||
current: list[str] = []
|
||||
depth = 0
|
||||
quote_char: str | None = None
|
||||
escaped = False
|
||||
|
||||
for char in text.strip():
|
||||
if quote_char is not None:
|
||||
current.append(char)
|
||||
if escaped:
|
||||
escaped = False
|
||||
elif char == "\\":
|
||||
escaped = True
|
||||
elif char == quote_char:
|
||||
quote_char = None
|
||||
continue
|
||||
|
||||
if char in {"'", '"'}:
|
||||
quote_char = char
|
||||
current.append(char)
|
||||
continue
|
||||
|
||||
if char in "([{":
|
||||
depth += 1
|
||||
current.append(char)
|
||||
continue
|
||||
|
||||
if char in ")]}":
|
||||
depth -= 1
|
||||
current.append(char)
|
||||
continue
|
||||
|
||||
if char.isspace() and depth == 0:
|
||||
if current:
|
||||
parts.append("".join(current))
|
||||
current = []
|
||||
continue
|
||||
|
||||
current.append(char)
|
||||
|
||||
if quote_char is not None or depth != 0:
|
||||
raise ValueError(f"Cannot parse input values: {text}")
|
||||
|
||||
if current:
|
||||
parts.append("".join(current))
|
||||
|
||||
return parts
|
||||
|
||||
|
||||
def parse_input_values(text: str) -> tuple[object, ...]:
|
||||
parts = split_top_level_values(text)
|
||||
if not parts:
|
||||
raise ValueError("No input values found")
|
||||
|
||||
return tuple(ast.literal_eval(part) for part in parts)
|
||||
|
||||
def parse_instructions(text: str) -> tuple[str, list[Example]]:
|
||||
examples: list[Example] = []
|
||||
function_name: str | None = None
|
||||
|
||||
for raw_line in text.splitlines():
|
||||
line = raw_line.strip()
|
||||
if not line:
|
||||
continue
|
||||
|
||||
left, right = line.split("==", maxsplit=1)
|
||||
match = re.match(r"^--\s*([A-Za-z_][A-Za-z0-9_]*)\s+(.*)$", left.strip())
|
||||
if match is None:
|
||||
raise ValueError(f"Cannot parse instruction line: {raw_line}")
|
||||
|
||||
current_name = match.group(1)
|
||||
if function_name is None:
|
||||
function_name = current_name
|
||||
elif function_name != current_name:
|
||||
raise ValueError("All instruction lines must use the same function name")
|
||||
|
||||
examples.append(
|
||||
Example(
|
||||
input_values=parse_input_values(match.group(2).strip()),
|
||||
expected_value=ast.literal_eval(right.strip()),
|
||||
)
|
||||
)
|
||||
|
||||
if function_name is None:
|
||||
raise ValueError("No examples found in instructions")
|
||||
|
||||
return function_name, examples
|
||||
|
||||
def build_names(prefix: str, count: int) -> list[str]:
|
||||
return [f"{prefix}_{index}" for index in range(1, count + 1)]
|
||||
|
||||
def infer_python_type(value: object) -> str:
|
||||
if isinstance(value, bool):
|
||||
return "bool"
|
||||
if isinstance(value, int):
|
||||
return "int"
|
||||
if isinstance(value, str):
|
||||
return "str"
|
||||
if isinstance(value, list):
|
||||
inner_type = infer_python_type(value[0]) if value else "object"
|
||||
return f"list[{inner_type}]"
|
||||
if isinstance(value, tuple):
|
||||
inner_types = ", ".join(infer_python_type(item) for item in value)
|
||||
return f"tuple[{inner_types}]"
|
||||
return "object"
|
||||
|
||||
|
||||
def infer_go_type(value: object) -> str:
|
||||
if isinstance(value, bool):
|
||||
return "bool"
|
||||
if isinstance(value, int):
|
||||
return "int"
|
||||
if isinstance(value, str):
|
||||
return "string"
|
||||
if isinstance(value, list):
|
||||
inner_type = infer_go_type(value[0]) if value else "int"
|
||||
return f"[]{inner_type}"
|
||||
raise TypeError(f"Unsupported Go type: {value!r}")
|
||||
|
||||
|
||||
def infer_rust_type(value: object) -> str:
|
||||
if isinstance(value, bool):
|
||||
return "bool"
|
||||
if isinstance(value, int):
|
||||
return "i32"
|
||||
if isinstance(value, str):
|
||||
return "&str"
|
||||
if isinstance(value, list):
|
||||
inner_type = infer_rust_type(value[0]) if value else "i32"
|
||||
return f"Vec<{inner_type}>"
|
||||
if isinstance(value, tuple):
|
||||
inner_types = ", ".join(infer_rust_type(item) for item in value)
|
||||
return f"({inner_types})"
|
||||
raise TypeError(f"Unsupported Rust type: {value!r}")
|
||||
|
||||
|
||||
def infer_rust_param_type(value: object) -> str:
|
||||
if isinstance(value, list):
|
||||
inner_type = infer_rust_type(value[0]) if value else "i32"
|
||||
return f"&[{inner_type}]"
|
||||
return infer_rust_type(value)
|
||||
|
||||
|
||||
def render_python(value: object) -> str:
|
||||
return repr(value)
|
||||
|
||||
|
||||
def render_julia(value: object) -> str:
|
||||
if isinstance(value, str):
|
||||
return f'"{value}"'
|
||||
if isinstance(value, list):
|
||||
return "[" + ", ".join(render_julia(item) for item in value) + "]"
|
||||
if isinstance(value, tuple):
|
||||
return "(" + ", ".join(render_julia(item) for item in value) + ")"
|
||||
return str(value)
|
||||
|
||||
|
||||
def render_go(value: object) -> str:
|
||||
if isinstance(value, str):
|
||||
return f'"{value}"'
|
||||
if isinstance(value, list):
|
||||
return (
|
||||
f"{infer_go_type(value)}{{"
|
||||
+ ", ".join(render_go(item) for item in value)
|
||||
+ "}"
|
||||
)
|
||||
return str(value)
|
||||
|
||||
|
||||
def render_rust(value: object) -> str:
|
||||
if isinstance(value, str):
|
||||
return f'"{value}"'
|
||||
if isinstance(value, list):
|
||||
return "vec![" + ", ".join(render_rust(item) for item in value) + "]"
|
||||
if isinstance(value, tuple):
|
||||
return "(" + ", ".join(render_rust(item) for item in value) + ")"
|
||||
return str(value)
|
||||
|
||||
|
||||
def build_python_checks(function_name: str, examples: list[Example]) -> str:
|
||||
blocks: list[str] = []
|
||||
|
||||
for example in examples:
|
||||
lines: list[str] = []
|
||||
names = build_names("check", len(example.input_values))
|
||||
|
||||
for name, value in zip(names, example.input_values):
|
||||
lines.append(f"{name} = {render_python(value)}")
|
||||
|
||||
lines.append(
|
||||
f"print({function_name}({', '.join(names)}))"
|
||||
f" # {render_python(example.expected_value)}"
|
||||
)
|
||||
blocks.append("\n".join(lines))
|
||||
|
||||
return "\n\n".join(blocks)
|
||||
|
||||
|
||||
def build_julia_checks(function_name: str, examples: list[Example]) -> str:
|
||||
blocks: list[str] = []
|
||||
|
||||
for example in examples:
|
||||
lines: list[str] = []
|
||||
names = build_names("check", len(example.input_values))
|
||||
|
||||
for name, value in zip(names, example.input_values):
|
||||
lines.append(f"{name} = {render_julia(value)}")
|
||||
|
||||
lines.append(
|
||||
f"println({function_name}({', '.join(names)}))"
|
||||
f" # {render_julia(example.expected_value)}"
|
||||
)
|
||||
blocks.append("\n".join(lines))
|
||||
|
||||
return "\n\n".join(blocks)
|
||||
|
||||
def render_rust_call_arg(name: str, value: object) -> str:
|
||||
if isinstance(value, list):
|
||||
return f"&{name}"
|
||||
return name
|
||||
|
||||
def build_rust_checks(function_name: str, examples: list[Example]) -> str:
|
||||
blocks: list[str] = []
|
||||
|
||||
for example in examples:
|
||||
lines: list[str] = []
|
||||
names = build_names("check", len(example.input_values))
|
||||
|
||||
for name, value in zip(names, example.input_values):
|
||||
lines.append(f" let {name} = {render_rust(value)};")
|
||||
|
||||
call_args = ", ".join(
|
||||
render_rust_call_arg(name, value)
|
||||
for name, value in zip(names, example.input_values)
|
||||
)
|
||||
lines.append(
|
||||
f' println!("{{:?}}", {function_name}({call_args}));'
|
||||
f" // {render_python(example.expected_value)}"
|
||||
)
|
||||
blocks.append("\n".join(lines))
|
||||
|
||||
return "\n\n".join(blocks)
|
||||
|
||||
|
||||
def build_go_checks(function_name: str, examples: list[Example]) -> str:
|
||||
blocks: list[str] = []
|
||||
|
||||
for example in examples:
|
||||
lines: list[str] = [" {"]
|
||||
input_names = build_names("check", len(example.input_values))
|
||||
|
||||
for name, value in zip(input_names, example.input_values):
|
||||
lines.append(f" {name} := {render_go(value)}")
|
||||
|
||||
if isinstance(example.expected_value, tuple):
|
||||
result_names = build_names("result", len(example.expected_value))
|
||||
lines.append(
|
||||
f" {', '.join(result_names)} := "
|
||||
f"{function_name}({', '.join(input_names)})"
|
||||
)
|
||||
lines.append(
|
||||
f" fmt.Println({', '.join(result_names)})"
|
||||
f" // {render_python(example.expected_value)}"
|
||||
)
|
||||
else:
|
||||
lines.append(
|
||||
f" fmt.Println({function_name}({', '.join(input_names)}))"
|
||||
f" // {render_python(example.expected_value)}"
|
||||
)
|
||||
|
||||
lines.append(" }")
|
||||
blocks.append("\n".join(lines))
|
||||
|
||||
return "\n\n".join(blocks)
|
||||
|
||||
def default_python_value(value: object) -> str:
|
||||
if isinstance(value, bool):
|
||||
return "False"
|
||||
if isinstance(value, int):
|
||||
return "0"
|
||||
if isinstance(value, str):
|
||||
return '""'
|
||||
if isinstance(value, list):
|
||||
return "[]"
|
||||
if isinstance(value, tuple):
|
||||
return "(" + ", ".join(default_python_value(item) for item in value) + ")"
|
||||
return "None"
|
||||
|
||||
|
||||
def default_julia_value(value: object) -> str:
|
||||
if isinstance(value, bool):
|
||||
return "false"
|
||||
if isinstance(value, int):
|
||||
return "0"
|
||||
if isinstance(value, str):
|
||||
return '""'
|
||||
if isinstance(value, list):
|
||||
return "[]"
|
||||
if isinstance(value, tuple):
|
||||
return "(" + ", ".join(default_julia_value(item) for item in value) + ")"
|
||||
return "nothing"
|
||||
|
||||
|
||||
def default_rust_value(value: object) -> str:
|
||||
if isinstance(value, bool):
|
||||
return "false"
|
||||
if isinstance(value, int):
|
||||
return "0"
|
||||
if isinstance(value, str):
|
||||
return '""'
|
||||
if isinstance(value, list):
|
||||
return "vec![]"
|
||||
if isinstance(value, tuple):
|
||||
return "(" + ", ".join(default_rust_value(item) for item in value) + ")"
|
||||
raise TypeError(f"Unsupported Rust type: {value!r}")
|
||||
|
||||
|
||||
def default_go_value(value: object) -> str:
|
||||
if isinstance(value, bool):
|
||||
return "false"
|
||||
if isinstance(value, int):
|
||||
return "0"
|
||||
if isinstance(value, str):
|
||||
return '""'
|
||||
if isinstance(value, list):
|
||||
return f"{infer_go_type(value)}{{}}"
|
||||
if isinstance(value, tuple):
|
||||
return ", ".join(default_go_value(item) for item in value)
|
||||
raise TypeError(f"Unsupported Go type: {value!r}")
|
||||
|
||||
|
||||
def infer_go_signature_return(value: object) -> str:
|
||||
if isinstance(value, tuple):
|
||||
return "(" + ", ".join(infer_go_type(item) for item in value) + ")"
|
||||
return infer_go_type(value)
|
||||
|
||||
def comment_block(prefix: str, text: str) -> str:
|
||||
return "\n".join(
|
||||
f"{prefix} {line}".rstrip()
|
||||
for line in text.splitlines()
|
||||
)
|
||||
|
||||
def create_if_missing(
|
||||
output_path: Path,
|
||||
creator: Callable[[Path, str, list[Example]], None],
|
||||
function_name: str,
|
||||
examples: list[Example],
|
||||
) -> None:
|
||||
if output_path.exists():
|
||||
return
|
||||
|
||||
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
creator(output_path, function_name, examples)
|
||||
|
||||
def create_python(
|
||||
problem_py: Path,
|
||||
function_name: str,
|
||||
examples: list[Example],
|
||||
) -> None:
|
||||
input_names = build_names("value", len(examples[0].input_values))
|
||||
params = ", ".join(
|
||||
f"{name}: {infer_python_type(value)}"
|
||||
for name, value in zip(input_names, examples[0].input_values)
|
||||
)
|
||||
return_type = infer_python_type(examples[0].expected_value)
|
||||
|
||||
template = "\n".join(
|
||||
[
|
||||
f"def {function_name}({params}) -> {return_type}:",
|
||||
f" return {default_python_value(examples[0].expected_value)}",
|
||||
"",
|
||||
build_python_checks(function_name, examples),
|
||||
"",
|
||||
]
|
||||
)
|
||||
problem_py.write_text(template, encoding="utf-8")
|
||||
|
||||
|
||||
def create_julia(
|
||||
problem_jl: Path,
|
||||
function_name: str,
|
||||
examples: list[Example],
|
||||
) -> None:
|
||||
params = ", ".join(build_names("value", len(examples[0].input_values)))
|
||||
|
||||
template = "\n".join(
|
||||
[
|
||||
f"function {function_name}({params})",
|
||||
f" return {default_julia_value(examples[0].expected_value)}",
|
||||
"end",
|
||||
"",
|
||||
build_julia_checks(function_name, examples),
|
||||
"",
|
||||
]
|
||||
)
|
||||
problem_jl.write_text(template, encoding="utf-8")
|
||||
|
||||
|
||||
def create_rust(
|
||||
problem_rs: Path,
|
||||
function_name: str,
|
||||
examples: list[Example],
|
||||
) -> None:
|
||||
input_names = build_names("value", len(examples[0].input_values))
|
||||
params = ", ".join(
|
||||
f"{name}: {infer_rust_param_type(value)}"
|
||||
for name, value in zip(input_names, examples[0].input_values)
|
||||
)
|
||||
return_type = infer_rust_type(examples[0].expected_value)
|
||||
|
||||
template = "\n".join(
|
||||
[
|
||||
f"fn {function_name}({params}) -> {return_type} {{",
|
||||
f" {default_rust_value(examples[0].expected_value)}",
|
||||
"}",
|
||||
"",
|
||||
"fn main() {",
|
||||
build_rust_checks(function_name, examples),
|
||||
"}",
|
||||
"",
|
||||
]
|
||||
)
|
||||
problem_rs.write_text(template, encoding="utf-8")
|
||||
|
||||
|
||||
def create_go(
|
||||
problem_go: Path,
|
||||
function_name: str,
|
||||
examples: list[Example],
|
||||
) -> None:
|
||||
input_names = build_names("value", len(examples[0].input_values))
|
||||
params = ", ".join(
|
||||
f"{name} {infer_go_type(value)}"
|
||||
for name, value in zip(input_names, examples[0].input_values)
|
||||
)
|
||||
return_type = infer_go_signature_return(examples[0].expected_value)
|
||||
|
||||
template = "\n".join(
|
||||
[
|
||||
"package main",
|
||||
"",
|
||||
'import "fmt"',
|
||||
"",
|
||||
f"func {function_name}({params}) {return_type} " + "{",
|
||||
f" return {default_go_value(examples[0].expected_value)}",
|
||||
"}",
|
||||
"",
|
||||
"func main() {",
|
||||
build_go_checks(function_name, examples),
|
||||
"}",
|
||||
"",
|
||||
]
|
||||
)
|
||||
problem_go.write_text(template, encoding="utf-8")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = ArgumentParser(description=__doc__)
|
||||
parser.add_argument(
|
||||
"-p",
|
||||
"--problem-number",
|
||||
dest="problem_number",
|
||||
type=int,
|
||||
required=True,
|
||||
help="number of the problem to solve",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
base_dir = Path(__file__).resolve().parent
|
||||
instructions = load_instructions(base_dir / "instructions.txt")
|
||||
|
||||
problem_stem = f"{args.problem_number:03d}"
|
||||
problem_py = base_dir / "Python" / f"{problem_stem}.py"
|
||||
problem_jl = base_dir / "Julia" / f"{problem_stem}.jl"
|
||||
problem_rs = base_dir / "Rust" / f"{problem_stem}.rs"
|
||||
problem_go = base_dir / "Go" / f"{problem_stem}.go"
|
||||
|
||||
function_name, examples = parse_instructions(instructions)
|
||||
|
||||
create_if_missing(problem_py, create_python, function_name, examples)
|
||||
create_if_missing(problem_jl, create_julia, function_name, examples)
|
||||
create_if_missing(problem_rs, create_rust, function_name, examples)
|
||||
create_if_missing(problem_go, create_go, function_name, examples)
|
||||
Reference in New Issue
Block a user