mirror of
https://github.com/fredrikr79/advent_of_code.git
synced 2026-01-11 20:03:06 +01:00
wip
This commit is contained in:
3
2025/10/prolog/example.pl
Normal file
3
2025/10/prolog/example.pl
Normal file
@@ -0,0 +1,3 @@
|
||||
input([0,1,1,0], [[3], [1,3], [2], [2,3], [0,2], [0,1]], [3,5,4,7]).
|
||||
input([0,0,0,1,0], [[0,2,3,4], [2,3], [0,4], [0,1,2], [1,2,3,4]], [7,5,12,7,2]).
|
||||
input([0,1,1,1,0,1], [[0,1,2,3,4], [0,3,4], [0,1,2,4,5], [1,2]], [10,11,11,5,10,5]).
|
||||
46
2025/10/prolog/main.pl
Normal file
46
2025/10/prolog/main.pl
Normal file
@@ -0,0 +1,46 @@
|
||||
% [.##.] (3) (1,3) (2) (2,3) (0,2) (0,1) {3,5,4,7}
|
||||
% [...#.] (0,2,3,4) (2,3) (0,4) (0,1,2) (1,2,3,4) {7,5,12,7,2}
|
||||
% [.###.#] (0,1,2,3,4) (0,3,4) (0,1,2,4,5) (1,2) {10,11,11,5,10,5}
|
||||
% -> 2 + 3 + 2 = 7
|
||||
|
||||
:- consult('example.pl').
|
||||
|
||||
% Keep your toggle functions
|
||||
toggle(Ls, [], Ls).
|
||||
toggle(Ls, [I|Is], Out) :-
|
||||
nth0(I, Ls, V), flip(V, F), set_nth0(I, Ls, F, T), toggle(T, Is, Out).
|
||||
flip(0, 1). flip(1, 0).
|
||||
set_nth0(0, [_|Rs], V, [V|Rs]).
|
||||
set_nth0(N, [R|Rs], V, [R|Ts]) :- N > 0, N1 is N-1, set_nth0(N1, Rs, V, Ts).
|
||||
|
||||
% Simple iterative deepening - no visited states needed
|
||||
solve(L, _, [], 0) :- maplist(=(1), L).
|
||||
solve(L, Wires, [W|Rest], D) :-
|
||||
D > 0, member(W, Wires),
|
||||
toggle(L, W, L1),
|
||||
D1 is D - 1,
|
||||
solve(L1, Wires, Rest, D1).
|
||||
|
||||
% Find minimal solution
|
||||
min_solve(L, Wires, Steps) :-
|
||||
between(0, 6, Depth), % Limit depth to 6
|
||||
length(Steps, Depth),
|
||||
solve(L, Wires, Steps, Depth).
|
||||
|
||||
|
||||
solve_all :-
|
||||
findall([L,W], input(L,W,_), Inputs),
|
||||
maplist(solve_one, Inputs, Lengths),
|
||||
sum_list(Lengths, Total),
|
||||
format('Total: ~w~n', [Total]).
|
||||
|
||||
solve_one([L,W], MinLen) :-
|
||||
find_min_depth(L, W, MinDepth),
|
||||
MinLen = MinDepth.
|
||||
|
||||
find_min_depth(L, Wires, MinDepth) :-
|
||||
between(0, 6, Depth),
|
||||
length(Steps, Depth),
|
||||
solve(L, Wires, Steps, Depth), !,
|
||||
MinDepth = Depth.
|
||||
|
||||
40
2025/11/uiua/alt.ua
Normal file
40
2025/11/uiua/alt.ua
Normal file
@@ -0,0 +1,40 @@
|
||||
# day 11
|
||||
|
||||
Parse ← (
|
||||
⊜(∩□⊙(⊜∘⊸≠@ )°$"_: _")⊸≠@\n
|
||||
∧(insert°□°⊟)⊙[]⍉⊟
|
||||
)
|
||||
Go‼ ← ⊙◌path(0°□⍣get|≍^1)^0
|
||||
Part₁ ← ⧻Go‼"you" "out"
|
||||
# Part₂ ← ⧻⊚≡◇(↧∩/↥⌕□"fft"⤙⌕□"dac"≡□)Go‼"svr" "out"
|
||||
Win‼ ← (
|
||||
⊃Go‼^0 "out" Go‼"svr" ^0
|
||||
+⊃(×⊙/+⧻|×⊙⧻/+)∩≡◇(/↥≡/↥⌕^1)
|
||||
)
|
||||
Part₂ ← ↥⊃Win‼"fft" "dac" Win‼"dac" "fft"
|
||||
⍤⤙≍ 5 Part₁ Parse $ aaa: you hhh
|
||||
$ you: bbb ccc
|
||||
$ bbb: ddd eee
|
||||
$ ccc: ddd eee fff
|
||||
$ ddd: ggg
|
||||
$ eee: out
|
||||
$ fff: out
|
||||
$ ggg: out
|
||||
$ hhh: ccc fff iii
|
||||
$ iii: out
|
||||
|
||||
⍤⤙≍ 2 Part₂ Parse $ svr: aaa bbb
|
||||
$ aaa: fft
|
||||
$ fft: ccc
|
||||
$ bbb: tty
|
||||
$ tty: ccc
|
||||
$ ccc: ddd eee
|
||||
$ ddd: hub
|
||||
$ hub: fff
|
||||
$ eee: dac
|
||||
$ dac: fff
|
||||
$ fff: ggg hhh
|
||||
$ ggg: out
|
||||
$ hhh: out
|
||||
|
||||
⍜now(Part₂ Parse &fras "input")
|
||||
36
2025/11/uiua/main.ua
Normal file
36
2025/11/uiua/main.ua
Normal file
@@ -0,0 +1,36 @@
|
||||
# day 11
|
||||
|
||||
Parse ← (
|
||||
⊜(∩□⊙(⊜∘⊸≠@ )°$"_: _")⊸≠@\n
|
||||
∧(insert°□°⊟)⊙[]⍉⊟
|
||||
)
|
||||
Go‼ ← ⊙◌path(0°□memoget|≍^1)^0
|
||||
Part₁ ← ⧻Go‼"you" "out"
|
||||
Part₂ ← ⧻⊚≡◇(↧∩/↥⌕□"fft"⤙⌕□"dac"≡□)Go‼"svr" "out"
|
||||
|
||||
⍤⤙≍ 5 Part₁ Parse $ aaa: you hhh
|
||||
$ you: bbb ccc
|
||||
$ bbb: ddd eee
|
||||
$ ccc: ddd eee fff
|
||||
$ ddd: ggg
|
||||
$ eee: out
|
||||
$ fff: out
|
||||
$ ggg: out
|
||||
$ hhh: ccc fff iii
|
||||
$ iii: out
|
||||
|
||||
⍤⤙≍ 2 Part₂ Parse $ svr: aaa bbb
|
||||
$ aaa: fft
|
||||
$ fft: ccc
|
||||
$ bbb: tty
|
||||
$ tty: ccc
|
||||
$ ccc: ddd eee
|
||||
$ ddd: hub
|
||||
$ hub: fff
|
||||
$ eee: dac
|
||||
$ dac: fff
|
||||
$ fff: ggg hhh
|
||||
$ ggg: out
|
||||
$ hhh: out
|
||||
|
||||
⍜now(Part₂ Parse &fras "input")
|
||||
BIN
2025/2/odin/main
Executable file
BIN
2025/2/odin/main
Executable file
Binary file not shown.
76
2025/2/odin/main.odin
Normal file
76
2025/2/odin/main.odin
Normal file
@@ -0,0 +1,76 @@
|
||||
package day2
|
||||
|
||||
import "core:fmt"
|
||||
import "core:math"
|
||||
import "core:strconv"
|
||||
import "core:strings"
|
||||
|
||||
EXAMPLE_INPUT :: "11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528,446443-446449,38593856-38593862,565653-565659,824824821-824824827,2121212118-2121212124"
|
||||
RANGE_COUNT :: 11
|
||||
|
||||
Data :: [RANGE_COUNT][2]int
|
||||
|
||||
// split input string into an array of each range end point
|
||||
parse :: proc(input: string, allocator := context.allocator) -> (data: ^Data, ok: bool) {
|
||||
defer free_all(context.temp_allocator)
|
||||
data = new(Data, allocator)
|
||||
ranges, err := strings.split_n(input, ",", RANGE_COUNT, context.temp_allocator)
|
||||
if err != .None do return nil, false
|
||||
for range, i in ranges {
|
||||
if i > RANGE_COUNT do break
|
||||
endpoints, err := strings.split_n(range, "-", 2, context.temp_allocator)
|
||||
if err != .None do return nil, false
|
||||
for j := 0; j < 2; j += 1 do data[i][j] = strconv.parse_int(endpoints[j]) or_return
|
||||
}
|
||||
return data, true
|
||||
}
|
||||
|
||||
part_1 :: proc(data: ^Data) -> (sum: int) {
|
||||
defer free_all(context.temp_allocator)
|
||||
sum = 0
|
||||
for range in data {
|
||||
start := range[0]
|
||||
end := range[1]
|
||||
start_digit_count := int(math.log10(f32(start))) + 1
|
||||
end_digit_count := int(math.log10(f32(end))) + 1
|
||||
if start_digit_count == end_digit_count && start_digit_count % 2 != 0 do continue
|
||||
if start_digit_count % 2 != 0 {
|
||||
start = end
|
||||
start_digit_count = end_digit_count
|
||||
}
|
||||
if end_digit_count % 2 != 0 {
|
||||
end = start
|
||||
end_digit_count = start_digit_count
|
||||
}
|
||||
for j := strconv.atoi(string(start)[:start_digit_count / 2 + 1]);
|
||||
j < strconv.atoi(string(end)[:end_digit_count / 2 + 1]);
|
||||
j += 1 {}
|
||||
start_str := make([]u8, start_digit_count, context.temp_allocator)
|
||||
strconv.itoa(start_str, start)
|
||||
for i := 0; i < start_digit_count; i += 1 {
|
||||
if i >= start_digit_count / 2 {
|
||||
start_str[i] = start_str[i % (start_digit_count / 2)]
|
||||
}
|
||||
}
|
||||
end_str := make([]u8, end_digit_count, context.temp_allocator)
|
||||
strconv.itoa(end_str, end)
|
||||
for i := 0; i < end_digit_count; i += 1 {
|
||||
if i >= end_digit_count / 2 {
|
||||
end_str[i] = end_str[i % (end_digit_count / 2)]
|
||||
}
|
||||
}
|
||||
fmt.println(start, end, strconv.atoi(string(start_str)), strconv.atoi(string(end_str)))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
data, ok := parse(EXAMPLE_INPUT)
|
||||
if !ok do panic("failed to parse")
|
||||
defer free(data)
|
||||
|
||||
part_1(data)
|
||||
|
||||
fmt.println(data)
|
||||
|
||||
}
|
||||
141
2025/3/odin/main.odin
Normal file
141
2025/3/odin/main.odin
Normal file
@@ -0,0 +1,141 @@
|
||||
package day3
|
||||
|
||||
import "core:fmt"
|
||||
import "core:mem"
|
||||
import "core:os"
|
||||
import "core:strings"
|
||||
import "core:time"
|
||||
|
||||
PUZZLE_INPUT :: `
|
||||
987654321111111
|
||||
811111111111119
|
||||
234234234234278
|
||||
818181911112111
|
||||
`
|
||||
|
||||
Data_Is_Empty_Error :: distinct struct{}
|
||||
|
||||
Data_Is_Ragged_Error :: distinct struct {
|
||||
line: int,
|
||||
}
|
||||
|
||||
Illegal_Token_Error :: distinct struct {
|
||||
line, col: int,
|
||||
token: rune,
|
||||
}
|
||||
|
||||
Parsing_Error :: union {
|
||||
mem.Allocator_Error,
|
||||
Illegal_Token_Error,
|
||||
Data_Is_Ragged_Error,
|
||||
Data_Is_Empty_Error,
|
||||
}
|
||||
|
||||
Grid :: struct {
|
||||
data: []int,
|
||||
rows, cols: int,
|
||||
}
|
||||
|
||||
parse :: proc(input: string, allocator := context.allocator) -> (grid: Grid, err: Parsing_Error) {
|
||||
context.allocator = context.temp_allocator
|
||||
defer context.allocator = allocator
|
||||
|
||||
lines := strings.split_lines(strings.trim_space(input)) or_return
|
||||
if lines[0] == "" do return {}, Data_Is_Empty_Error{}
|
||||
|
||||
rows := len(lines)
|
||||
cols := len(strings.trim_space(lines[0]))
|
||||
|
||||
data := make([dynamic]int, 0, rows * cols, allocator) or_return
|
||||
|
||||
for line, row in lines {
|
||||
clean_line := strings.trim_space(line)
|
||||
if len(clean_line) != cols do return {}, Data_Is_Ragged_Error{row}
|
||||
|
||||
for char, col in clean_line {
|
||||
digit := int(char - '0')
|
||||
if digit < 0 || digit > 9 do return {}, Illegal_Token_Error{row, col, char}
|
||||
append(&data, digit) or_return
|
||||
}
|
||||
}
|
||||
|
||||
return Grid{data[:], rows, cols}, nil
|
||||
}
|
||||
|
||||
remove_digits :: proc(
|
||||
row: []int,
|
||||
k: int,
|
||||
allocator := context.allocator,
|
||||
) -> (
|
||||
output: []int,
|
||||
err: mem.Allocator_Error,
|
||||
) {
|
||||
stack := make([dynamic]int, 0, len(row) - k, allocator) or_return
|
||||
dels := k
|
||||
for digit in row {
|
||||
for len(stack) > 0 && digit > stack[len(stack) - 1] && dels > 0 {
|
||||
pop(&stack)
|
||||
dels -= 1
|
||||
}
|
||||
append(&stack, digit) or_return
|
||||
}
|
||||
return stack[:], .None
|
||||
}
|
||||
|
||||
process :: proc(row: []int, n: int) -> (output: int, err: mem.Allocator_Error) {
|
||||
digits := remove_digits(row, len(row) - n) or_return
|
||||
for digit in digits[:n] {
|
||||
output = 10 * output + digit
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
solve :: proc(grid: Grid, n: int) -> (solution: int, err: mem.Allocator_Error) {
|
||||
context.allocator = context.temp_allocator
|
||||
|
||||
bank_solutions := make([]int, grid.rows) or_return
|
||||
|
||||
for row in 0 ..< grid.rows {
|
||||
row_data := grid.data[row * grid.cols:(row + 1) * grid.cols]
|
||||
bank_solutions[row] = process(row_data, n) or_return
|
||||
}
|
||||
|
||||
for bank in bank_solutions do solution += bank
|
||||
return
|
||||
}
|
||||
|
||||
part_1 :: proc(grid: Grid) -> (solution: int, err: mem.Allocator_Error) {
|
||||
return solve(grid, 2)
|
||||
}
|
||||
|
||||
part_2 :: proc(grid: Grid) -> (solution: int, err: mem.Allocator_Error) {
|
||||
return solve(grid, 12)
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
time_start := time.now()
|
||||
input := string(os.read_entire_file("input") or_else panic("failed to read input"))
|
||||
time_read := time.since(time_start)
|
||||
|
||||
data, parsing_error := parse(input, context.temp_allocator)
|
||||
defer free_all(context.temp_allocator)
|
||||
if parsing_error != nil do fmt.panicf("failed to parse: %v\n", parsing_error)
|
||||
|
||||
time_parse := time.since(time_start) - time_read
|
||||
fmt.println("part 1: ", part_1(data) or_else panic("part 1 failed"))
|
||||
time_solve_1 := time.since(time_start) - time_read - time_parse
|
||||
fmt.println("part 2: ", part_2(data) or_else panic("part 2 failed"))
|
||||
time_solve_2 := time.since(time_start) - time_read - time_parse - time_solve_1
|
||||
time_total := time.since(time_start)
|
||||
|
||||
fmt.println("performance benchmarks [ms]:")
|
||||
fmt.println("total\tread\tparse\tpart 1\tpart 2")
|
||||
fmt.printf(
|
||||
"%.3f\t%.3f\t%.3f\t%.3f\t%.3f\n",
|
||||
time.duration_milliseconds(time_total),
|
||||
time.duration_milliseconds(time_read),
|
||||
time.duration_milliseconds(time_parse),
|
||||
time.duration_milliseconds(time_solve_1),
|
||||
time.duration_milliseconds(time_solve_2),
|
||||
)
|
||||
}
|
||||
20
2025/5/uiua/main.ua
Normal file
20
2025/5/uiua/main.ua
Normal file
@@ -0,0 +1,20 @@
|
||||
Parse ← (
|
||||
∩(⊜□⊸≠@\n)°$"_\n\n_"
|
||||
⊃(⍉⊟≡◇(∩⋕°$"_-_")|⋅≡◇⋕)
|
||||
)
|
||||
Part₁ ← ⧻⊚/↥⊞(↧≤⤙⊙≤°⊟)
|
||||
Part₂ ← ⧻◴/◇⊂⍚/⍜-(⇡+1)
|
||||
|
||||
⍤⤙≍ 3_14 ⊃[Part₁|Part₂] Parse $ 3-5
|
||||
$ 10-14
|
||||
$ 16-20
|
||||
$ 12-18
|
||||
$
|
||||
$ 1
|
||||
$ 5
|
||||
$ 8
|
||||
$ 11
|
||||
$ 17
|
||||
$ 32
|
||||
|
||||
Part₂ Parse &fras "input.txt"
|
||||
16
2025/7/odin/example
Normal file
16
2025/7/odin/example
Normal file
@@ -0,0 +1,16 @@
|
||||
.......S.......
|
||||
...............
|
||||
.......^.......
|
||||
...............
|
||||
......^.^......
|
||||
...............
|
||||
.....^.^.^.....
|
||||
...............
|
||||
....^.^...^....
|
||||
...............
|
||||
...^.^...^.^...
|
||||
...............
|
||||
..^...^.....^..
|
||||
...............
|
||||
.^.^.^.^.^...^.
|
||||
...............
|
||||
101
2025/7/odin/main.odin
Normal file
101
2025/7/odin/main.odin
Normal file
@@ -0,0 +1,101 @@
|
||||
package day7
|
||||
|
||||
import "core:fmt"
|
||||
import "core:slice"
|
||||
import "core:strings"
|
||||
import "core:time"
|
||||
|
||||
PUZZLE_INPUT: string : #load("input")
|
||||
|
||||
Pos :: distinct struct {
|
||||
row: int,
|
||||
col: int,
|
||||
}
|
||||
|
||||
Parsed_Data :: struct {
|
||||
lines: []string,
|
||||
rows, cols: int,
|
||||
start: Pos,
|
||||
}
|
||||
|
||||
not_empty_line :: proc(line: string) -> (output: bool) {
|
||||
output = true
|
||||
for char in line do output &&= char == '.'
|
||||
return !output
|
||||
}
|
||||
|
||||
parse :: proc(input: string) -> (output: Parsed_Data) {
|
||||
lines := strings.split_lines(input)
|
||||
output.start = {0, strings.index(lines[0], "S")}
|
||||
output.lines = slice.filter(lines, not_empty_line)
|
||||
output.rows = len(output.lines)
|
||||
output.cols = len(output.lines[0])
|
||||
return
|
||||
}
|
||||
|
||||
solve_part_1 :: proc(data: Parsed_Data) -> (output: int) {
|
||||
beams := make(map[Pos]bool, context.temp_allocator)
|
||||
hit := make(map[Pos]bool, context.temp_allocator)
|
||||
defer free_all(context.temp_allocator)
|
||||
beams[data.start] = true
|
||||
for line, row in data.lines {
|
||||
for char, col in line {
|
||||
for pos, exists in beams {
|
||||
if exists && char == '^' && pos == {row - 1, col} {
|
||||
beams[{row, col + 1}] = true
|
||||
beams[{row, col - 1}] = true
|
||||
hit[{row, col}] = true
|
||||
} else if pos == {row - 1, col} {
|
||||
beams[{row, col}] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return len(hit)
|
||||
}
|
||||
|
||||
solve_part_2 :: proc(data: Parsed_Data) -> (output: int) {
|
||||
memo := make(map[Pos]int)
|
||||
defer delete(memo)
|
||||
|
||||
count_timelines :: proc(lines: []string, row, col: int, memo: ^map[Pos]int) -> int {
|
||||
pos := Pos{row, col}
|
||||
|
||||
// Check memo first
|
||||
if cached, exists := memo[pos]; exists {
|
||||
return cached
|
||||
}
|
||||
|
||||
// Bounds check
|
||||
if row >= len(lines) || col < 0 || col >= len(lines[0]) {
|
||||
memo[pos] = 1
|
||||
return 1
|
||||
}
|
||||
|
||||
char := lines[row][col]
|
||||
result: int
|
||||
|
||||
if char == '^' {
|
||||
left := count_timelines(lines, row + 1, col - 1, memo)
|
||||
right := count_timelines(lines, row + 1, col + 1, memo)
|
||||
result = left + right
|
||||
} else {
|
||||
result = count_timelines(lines, row + 1, col, memo)
|
||||
}
|
||||
|
||||
memo[pos] = result
|
||||
return result
|
||||
}
|
||||
|
||||
return count_timelines(data.lines, data.start.row, data.start.col, &memo)
|
||||
}
|
||||
|
||||
|
||||
main :: proc() {
|
||||
start := time.now()
|
||||
data := parse(PUZZLE_INPUT)
|
||||
fmt.println("part 1 solution:", solve_part_1(data))
|
||||
fmt.println("part 2 solution:", solve_part_2(data))
|
||||
total := time.since(start)
|
||||
fmt.println("total time taken:", total)
|
||||
}
|
||||
BIN
2025/8/debug_build
Executable file
BIN
2025/8/debug_build
Executable file
Binary file not shown.
20
2025/8/example
Normal file
20
2025/8/example
Normal file
@@ -0,0 +1,20 @@
|
||||
162,817,812
|
||||
57,618,57
|
||||
906,360,560
|
||||
592,479,940
|
||||
352,342,300
|
||||
466,668,158
|
||||
542,29,236
|
||||
431,825,988
|
||||
739,650,466
|
||||
52,470,668
|
||||
216,146,977
|
||||
819,987,18
|
||||
117,168,530
|
||||
805,96,715
|
||||
346,949,466
|
||||
970,615,88
|
||||
941,993,340
|
||||
862,61,35
|
||||
984,92,344
|
||||
425,690,689
|
||||
50
2025/8/main.odin
Normal file
50
2025/8/main.odin
Normal file
@@ -0,0 +1,50 @@
|
||||
package main
|
||||
|
||||
import "core:fmt"
|
||||
import "core:slice"
|
||||
import "core:strconv"
|
||||
import "core:strings"
|
||||
|
||||
PUZZLE_INPUT: string : #load("example")
|
||||
|
||||
Pos :: distinct struct {
|
||||
x, y, z: int,
|
||||
}
|
||||
|
||||
parse :: proc(input: string) -> (output: []Pos) {
|
||||
lines := strings.split_lines(input)
|
||||
output = make([]Pos, len(lines))
|
||||
digits := make([dynamic]int, context.temp_allocator)
|
||||
defer free_all(context.temp_allocator)
|
||||
nums: [3]int
|
||||
for line, row in lines {
|
||||
for num, i in strings.split(line, ",") do nums[i], _ = strconv.parse_int(num)
|
||||
output[row] = Pos{nums[0], nums[1], nums[2]}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
solve :: proc(data: []Pos) -> (output: int) {
|
||||
context.allocator = context.temp_allocator
|
||||
|
||||
distances := make([]int, len(data) * len(data))
|
||||
for p1, row in data {
|
||||
for p2, col in data {
|
||||
d := Pos{p1.x - p2.x, p1.y - p2.y, p1.z - p2.z}
|
||||
distance := d.x * d.x + d.y * d.y + d.z * d.z
|
||||
distances[row * len(data) + col] = distance == 0 ? 1e9 : distance // TODO: triangle
|
||||
}
|
||||
}
|
||||
fmt.println(distances)
|
||||
shortest := make([]int, len(data))
|
||||
for i in 0 ..< len(data) {
|
||||
row := distances[i * len(data):(i + 1) * len(data)]
|
||||
shortest[i] = slice.min_index(row)
|
||||
}
|
||||
fmt.println(shortest)
|
||||
return
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
fmt.println(solve(parse(PUZZLE_INPUT)))
|
||||
}
|
||||
Reference in New Issue
Block a user