Compare commits

...

23 Commits

Author SHA1 Message Date
7a37e28de1 Mastermind en Go 2026-05-24 10:49:40 +02:00
78efe71bc0 Mastermind en Rust 2026-05-24 10:49:23 +02:00
d72b651818 Mastermind en Julia 2026-05-24 10:49:01 +02:00
51ce912081 Mastermind en Python 2026-05-24 10:48:41 +02:00
77f92130bf Modificacion en plantilla para que acepte nuevos patrones de soluciones 2026-05-20 21:06:33 +02:00
b5fb1445fd Plantilla para generar esqueleto de soluciones 2026-05-17 17:11:50 +02:00
0a5969b2e0 Minimales en Go 2026-05-17 17:10:31 +02:00
c1a5ce4494 Minimales en Rust 2026-05-17 17:10:17 +02:00
55705a796a Minimales en Julia 2026-05-17 17:10:02 +02:00
aa176f7038 Minimales en Python 2026-05-17 17:09:45 +02:00
aa20952dc2 Bandera tricolor en Go 2026-05-10 18:58:35 +02:00
002fff8d1d Bandera tricolor en Rust 2026-05-10 18:58:26 +02:00
0d7a0f9986 Bandera tricolor en Julia 2026-05-10 18:58:13 +02:00
649de7b871 Bandera tricolor en Python 2026-05-10 18:58:03 +02:00
cbc9db76f2 Quitar ejecutable de Rust 2026-05-09 17:04:52 +02:00
7b032a1ef4 Ordenar por maximo en Rust 2026-05-09 17:03:37 +02:00
0c9bcca1ae Ordenar por maximo en Go 2026-05-09 17:03:18 +02:00
1ab98c2047 Ordenar por maximo en Julia 2026-05-09 17:03:04 +02:00
2f401b763a Ordenar por maximo en Python 2026-05-09 17:02:48 +02:00
0e2e9c2a34 Añadir atribución al autor de los problemas 2026-05-08 17:25:46 +02:00
7330e81ad2 Iguales al siguiente en Go 2026-05-08 17:21:46 +02:00
3546cd699f Iguales al siguiente en Julia 2026-05-08 17:08:38 +02:00
1069987fb4 Iguales al siguiente en Python 2026-05-08 16:59:29 +02:00
22 changed files with 1091 additions and 0 deletions

View File

@@ -1,2 +1,3 @@
# Exercitium
Ejercicios propuestos por @jaalonso [aqui](https://github.com/jaalonso/Exercitium) resueltos usando distintos lenguajes para practicar un poco

21
src/Go/001.go Normal file
View File

@@ -0,0 +1,21 @@
package main
import "fmt"
func same_to_next(lst []int) []int {
_lst := []int{}
for i := 0; i+1 < len(lst); i++ {
if lst[i] == lst[i+1] {
_lst = append(_lst, lst[i])
}
}
return _lst
}
func main() {
check := []int{1, 2, 2, 2, 3, 3, 4}
fmt.Println(same_to_next(check)) // [2 2 3]
check = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
fmt.Println(same_to_next(check)) // []
}

62
src/Go/002.go Normal file
View File

@@ -0,0 +1,62 @@
package main
import (
"fmt"
"sort"
)
func maxIntSlice(lst []int) int {
m := lst[0]
for _, v := range lst[1:] {
if v > m {
m = v
}
}
return m
}
func order_by_max_i32(lst [][]int) [][]int {
result := append([][]int(nil), lst...) // copy outer slice (like Python sorted)
sort.SliceStable(result, func(i int, j int) bool {
return maxIntSlice(result[i]) < maxIntSlice(result[j])
})
return result
}
func maxRune(s string) rune {
var m rune
for _, r := range s {
if r > m {
m = r
}
}
return m
}
func order_by_max_str(lst []string) []string {
result := append([]string(nil), lst...) // copy (like Python sorted)
sort.SliceStable(result, func(i int, j int) bool {
return maxRune(result[i]) < maxRune(result[j])
})
return result
}
func main() {
check := [][]int{{3, 2}, {6, 7, 5}, {1, 4}}
fmt.Println(order_by_max_i32(check)) // [[3,2],[1,4],[6,7,5]]
check = [][]int{{1}, {0, 1}}
fmt.Println(order_by_max_i32(check)) // [[1],[0,1]]
check = [][]int{{0, 1}, {1}}
fmt.Println(order_by_max_i32(check)) // [[0,1],[1]]
checkStr := []string{"este", "es", "el", "primero"}
fmt.Println(order_by_max_str(checkStr)) // ["el","primero","es","este"]
}

31
src/Go/003.go Normal file
View 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
View 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
View 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)
}
}

10
src/Julia/001.jl Normal file
View File

@@ -0,0 +1,10 @@
function same_to_next(lst)
return [x for (x, y) in zip(lst[1:end-1], lst[2:end]) if x == y]
end
check = [1, 2, 2, 2, 3, 3, 4]
println(same_to_next(check)) # [2, 2, 3]
check = collect(1:10)
println(same_to_next(check)) # Int64[]

16
src/Julia/002.jl Normal file
View File

@@ -0,0 +1,16 @@
function order_by_max(lst)
return sort(lst, by=maximum)
end
check = [[3,2],[6,7,5],[1,4]]
println(order_by_max(check)) # [[3,2],[1,4],[6,7,5]]
check = [[1],[0,1]]
println(order_by_max(check)) # [[1],[0,1]]
check = [[0,1],[1]]
println(order_by_max(check)) # [[0,1],[1]]
check = ["este","es","el","primero"]
println(order_by_max(check)) # ["el","primero","es","este"]

13
src/Julia/003.jl Normal file
View 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
View 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
View 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)

16
src/Python/001.py Normal file
View File

@@ -0,0 +1,16 @@
# def same_to_next(lst: list) -> list:
# same_to_next_lst = []
# for idx, element in enumerate(lst[:-1]):
# if lst[idx] == lst[idx+1]:
# same_to_next_lst.append(element)
# return same_to_next_lst
def same_to_next(lst: list) -> list:
return [x for x, y in zip(lst, lst[1:]) if x == y]
check = [1, 2, 2, 2, 3, 3, 4]
print(same_to_next(check)) # [2, 2, 3]
check = list(range(1, 11))
print(same_to_next(check)) # []

15
src/Python/002.py Normal file
View File

@@ -0,0 +1,15 @@
def order_by_max(lst: list) -> list:
return sorted(lst, key=max)
check = [[3,2],[6,7,5],[1,4]]
print(order_by_max(check)) # [[3,2],[1,4],[6,7,5]]
check = [[1],[0,1]]
print(order_by_max(check)) # [[1],[0,1]]
check = [[0,1],[1]]
print(order_by_max(check)) # [[0,1],[1]]
check = ["este","es","el","primero"]
print(order_by_max(check)) # ["el","primero","es","este"]

11
src/Python/003.py Normal file
View 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
View 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
View 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)

19
src/Rust/001.rs Normal file
View File

@@ -0,0 +1,19 @@
fn same_to_next(lst: &[i32]) -> Vec<i32> {
let mut _lst: Vec<i32> = Vec::new();
for idx in 0..(lst.len() - 1) {
if lst[idx] == lst[idx + 1] {
_lst.push(lst[idx]);
}
}
return _lst
}
fn main() {
let check = vec![1, 2, 2, 2, 3, 3, 4];
println!("{:?}", same_to_next(&check)); // [2, 2, 3]
let check: Vec<i32> = (1..=10).collect();
println!("{:?}", same_to_next(&check)); // []
}

27
src/Rust/002.rs Normal file
View File

@@ -0,0 +1,27 @@
fn order_by_max_i32(lst: &[Vec<i32>]) -> Vec<Vec<i32>> {
let mut sorted_lst = lst.to_vec();
sorted_lst.sort_by_key(|v| v.iter().max().cloned()); // stable sort by max element
return sorted_lst
}
fn order_by_max_str<'a>(lst: &[&'a str]) -> Vec<&'a str> {
let mut sorted_lst = lst.to_vec();
sorted_lst.sort_by_key(|s| s.chars().max()); // stable sort by max char
return sorted_lst
}
fn main() {
let check = vec![vec![3,2], vec![6,7,5], vec![1,4]];
println!("{:?}", order_by_max_i32(&check)); // [[3,2],[1,4],[6,7,5]]
let check = vec![vec![1], vec![0,1]];
println!("{:?}", order_by_max_i32(&check)); // [[1],[0,1]]
let check = vec![vec![0,1], vec![1]];
println!("{:?}", order_by_max_i32(&check)); // [[0,1],[1]]
let check = vec!["este","es","el","primero"];
println!("{:?}", order_by_max_str(&check)); // ["el","primero","es","este"]
}

20
src/Rust/003.rs Normal file
View 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
View 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
View 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
View 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)