chore: imporivements
This commit is contained in:
parent
127e9c33c6
commit
927fabebfc
|
@ -4,21 +4,12 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
aoc "go.sour.is/advent-of-code-2023"
|
aoc "go.sour.is/advent-of-code-2023"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() { aoc.MustResult(aoc.Runner(run)) }
|
||||||
result, err := aoc.Runner(run)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("ERR", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
type result struct {
|
type result struct {
|
||||||
sum int
|
sum int
|
||||||
|
|
|
@ -51,12 +51,10 @@ func run(scan *bufio.Scanner) (*result, error) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
games = append(games, []gameResult{})
|
rounds := aoc.SliceMap(func(text string) gameResult {
|
||||||
|
round := gameResult{}
|
||||||
|
|
||||||
for _, round := range strings.Split(text, ";") {
|
for _, result := range strings.Split(text, ",") {
|
||||||
game := gameResult{}
|
|
||||||
|
|
||||||
for _, result := range strings.Split(round, ",") {
|
|
||||||
ns, color, _ := strings.Cut(strings.TrimSpace(result), " ")
|
ns, color, _ := strings.Cut(strings.TrimSpace(result), " ")
|
||||||
n, err := strconv.Atoi(ns)
|
n, err := strconv.Atoi(ns)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -65,16 +63,17 @@ func run(scan *bufio.Scanner) (*result, error) {
|
||||||
|
|
||||||
switch color {
|
switch color {
|
||||||
case "red":
|
case "red":
|
||||||
game.red = n
|
round.red = n
|
||||||
case "green":
|
case "green":
|
||||||
game.green = n
|
round.green = n
|
||||||
case "blue":
|
case "blue":
|
||||||
game.blue = n
|
round.blue = n
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
games[len(games)-1] = append(games[len(games)-1], game)
|
return round
|
||||||
}
|
}, strings.Split(text, ";")...)
|
||||||
|
|
||||||
|
games = append(games, rounds)
|
||||||
}
|
}
|
||||||
|
|
||||||
aoc.Log(games)
|
aoc.Log(games)
|
||||||
|
|
|
@ -9,6 +9,8 @@ import (
|
||||||
aoc "go.sour.is/advent-of-code-2023"
|
aoc "go.sour.is/advent-of-code-2023"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func main() { aoc.MustResult(aoc.Runner(run)) }
|
||||||
|
|
||||||
type partNumber struct {
|
type partNumber struct {
|
||||||
number int
|
number int
|
||||||
row int
|
row int
|
||||||
|
@ -54,7 +56,6 @@ func (tab symbolTab) scanSymbol(p partNumber) bool {
|
||||||
// 553079
|
// 553079
|
||||||
// 84363105
|
// 84363105
|
||||||
|
|
||||||
func main() { aoc.MustResult(aoc.Runner(run)) }
|
|
||||||
|
|
||||||
type result struct {
|
type result struct {
|
||||||
valuePT1 int
|
valuePT1 int
|
||||||
|
@ -101,21 +102,23 @@ func run(scan *bufio.Scanner) (*result, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sum := 0
|
sum := aoc.SumIFunc(
|
||||||
for i, p := range parts {
|
func(i int, p partNumber) int {
|
||||||
ok := symbols.scanSymbol(p)
|
ok := symbols.scanSymbol(p)
|
||||||
parts[i].hasSymbol = ok
|
parts[i].hasSymbol = ok
|
||||||
if ok {
|
if ok {
|
||||||
sum += p.number
|
return p.number
|
||||||
}
|
}
|
||||||
}
|
return 0
|
||||||
|
}, parts...,)
|
||||||
|
|
||||||
sumGears := 0
|
sumGears := aoc.SumFunc(
|
||||||
for _, s := range symbolList {
|
func(s *symbol) int {
|
||||||
if s.symbol == '*' && len(s.adjacentParts) == 2 {
|
if s.symbol == '*' && len(s.adjacentParts) == 2 {
|
||||||
sumGears += s.adjacentParts[0].number * s.adjacentParts[1].number
|
return s.adjacentParts[0].number * s.adjacentParts[1].number
|
||||||
}
|
}
|
||||||
}
|
return 0
|
||||||
|
}, symbolList...)
|
||||||
|
|
||||||
// fmt.Println(parts)
|
// fmt.Println(parts)
|
||||||
// fmt.Println(symbols)
|
// fmt.Println(symbols)
|
||||||
|
|
|
@ -2,13 +2,12 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
aoc "go.sour.is/advent-of-code-2023"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed input.txt
|
//go:embed input.txt
|
||||||
|
@ -21,22 +20,14 @@ type card struct {
|
||||||
copies int
|
copies int
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() { aoc.MustResult(aoc.Runner(run)) }
|
||||||
var level slog.Level
|
|
||||||
if err := level.UnmarshalText([]byte(os.Getenv("DEBUG_LEVEL"))); err == nil && level != 0 {
|
|
||||||
slog.SetDefault(slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: level})))
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := bytes.NewReader(input)
|
type result struct {
|
||||||
scan := bufio.NewScanner(buf)
|
points int
|
||||||
|
cards int
|
||||||
points, cards := run(scan)
|
|
||||||
|
|
||||||
fmt.Println("points:", points)
|
|
||||||
fmt.Println("cards:", cards)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(scan *bufio.Scanner) (int, int) {
|
func run(scan *bufio.Scanner) (result, error) {
|
||||||
cards := []*card{}
|
cards := []*card{}
|
||||||
|
|
||||||
for scan.Scan() {
|
for scan.Scan() {
|
||||||
|
@ -46,7 +37,7 @@ func run(scan *bufio.Scanner) (int, int) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
num, _ := strconv.Atoi(strings.TrimSpace(strings.SplitN(pfx, " ", 2)[1]))
|
num := aoc.Atoi(strings.TrimSpace(strings.SplitN(pfx, " ", 2)[1]))
|
||||||
cards = append(cards, &card{card: num})
|
cards = append(cards, &card{card: num})
|
||||||
buf := make([]rune, 0, 4)
|
buf := make([]rune, 0, 4)
|
||||||
winner := true
|
winner := true
|
||||||
|
@ -71,7 +62,7 @@ func run(scan *bufio.Scanner) (int, int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(buf) > 0 {
|
if len(buf) > 0 {
|
||||||
num, _ = strconv.Atoi(string(buf))
|
num = aoc.Atoi(string(buf))
|
||||||
buf = buf[:0]
|
buf = buf[:0]
|
||||||
_ = buf // ignore
|
_ = buf // ignore
|
||||||
cards[len(cards)-1].scratch = append(cards[len(cards)-1].scratch, num)
|
cards[len(cards)-1].scratch = append(cards[len(cards)-1].scratch, num)
|
||||||
|
@ -105,5 +96,5 @@ func run(scan *bufio.Scanner) (int, int) {
|
||||||
slog.Debug("points", "card", card.card, "match", m, "score", sumPoints)
|
slog.Debug("points", "card", card.card, "match", m, "score", sumPoints)
|
||||||
}
|
}
|
||||||
|
|
||||||
return sumPoints, sumCards
|
return result{sumPoints, sumCards}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,27 +7,19 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
aoc "go.sour.is/advent-of-code-2023"
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() { aoc.MustResult(aoc.Runner(run)) }
|
||||||
if len(os.Args) != 2 {
|
|
||||||
fmt.Fprintln(os.Stderr, "Usage: day05 FILE")
|
|
||||||
}
|
|
||||||
|
|
||||||
input, err := os.Open(os.Args[1])
|
type result struct {
|
||||||
if err != nil {
|
minLocation int
|
||||||
fmt.Fprintln(os.Stderr, err)
|
minRange int
|
||||||
}
|
|
||||||
|
|
||||||
scan := bufio.NewScanner(input)
|
|
||||||
|
|
||||||
minLocation, minRangeLocation := run(scan)
|
|
||||||
|
|
||||||
fmt.Println("min location:", minLocation)
|
|
||||||
fmt.Println("min range location:", minRangeLocation)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(scan *bufio.Scanner) (int, int) {
|
func run(scan *bufio.Scanner) (result, error) {
|
||||||
log("begin...")
|
log("begin...")
|
||||||
|
|
||||||
var seeds []int
|
var seeds []int
|
||||||
|
@ -55,15 +47,14 @@ func run(scan *bufio.Scanner) (int, int) {
|
||||||
lookup["humidity-to-location"],
|
lookup["humidity-to-location"],
|
||||||
)
|
)
|
||||||
|
|
||||||
return findMinLocation(seeds, find), FindMinRangeLocationMulti(seedRanges, find)
|
return result{findMinLocation(seeds, find), FindMinRangeLocationMulti(seedRanges, find)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func readSeeds(text string) ([]int, [][2]int) {
|
func readSeeds(text string) ([]int, [][2]int) {
|
||||||
var seeds [] int
|
var seeds []int
|
||||||
var seedRanges [][2]int
|
var seedRanges [][2]int
|
||||||
sp := strings.Fields(strings.TrimPrefix(text, "seeds: "))
|
|
||||||
for i, s := range sp {
|
for i, n := range aoc.SliceMap(aoc.Atoi, strings.Fields(strings.TrimPrefix(text, "seeds: "))...) {
|
||||||
n, _ := strconv.Atoi(s)
|
|
||||||
seeds = append(seeds, n)
|
seeds = append(seeds, n)
|
||||||
|
|
||||||
if i%2 == 0 {
|
if i%2 == 0 {
|
||||||
|
@ -121,7 +112,7 @@ func FindMinRangeLocation(ranges [][2]int, find *Finder) int {
|
||||||
|
|
||||||
for _, s := range ranges {
|
for _, s := range ranges {
|
||||||
for i := 0; i < s[1]; i++ {
|
for i := 0; i < s[1]; i++ {
|
||||||
seedLocations = append(seedLocations, find.Find(s[0] + i))
|
seedLocations = append(seedLocations, find.Find(s[0]+i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return min(seedLocations...)
|
return min(seedLocations...)
|
||||||
|
@ -164,7 +155,7 @@ func FindMinRangeLocationMulti(ranges [][2]int, find *Finder) int {
|
||||||
seedLocations := make([]int, 0, results)
|
seedLocations := make([]int, 0, results)
|
||||||
expectResults := make([]struct{}, len(ranges))
|
expectResults := make([]struct{}, len(ranges))
|
||||||
for range expectResults {
|
for range expectResults {
|
||||||
r := <- resultsCh
|
r := <-resultsCh
|
||||||
seedLocations = append(seedLocations, r...)
|
seedLocations = append(seedLocations, r...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,29 +3,19 @@ package main
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
aoc "go.sour.is/advent-of-code-2023"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() { aoc.MustResult(aoc.Runner(run)) }
|
||||||
if len(os.Args) != 2 {
|
|
||||||
fmt.Fprintln(os.Stderr, "Usage: day07 FILE")
|
|
||||||
}
|
|
||||||
|
|
||||||
input, err := os.Open(os.Args[1])
|
type result struct {
|
||||||
if err != nil {
|
valuePT1 uint64
|
||||||
fmt.Fprintln(os.Stderr, err)
|
valuePT2 uint64
|
||||||
}
|
|
||||||
|
|
||||||
scan := bufio.NewScanner(input)
|
|
||||||
|
|
||||||
score1, score2 := run(scan)
|
|
||||||
|
|
||||||
fmt.Println("score 1", score1)
|
|
||||||
fmt.Println("score 2", score2)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(scan *bufio.Scanner) (uint64, uint64) {
|
func run(scan *bufio.Scanner) (result, error) {
|
||||||
var game Game
|
var game Game
|
||||||
|
|
||||||
for scan.Scan() {
|
for scan.Scan() {
|
||||||
|
@ -47,7 +37,7 @@ func run(scan *bufio.Scanner) (uint64, uint64) {
|
||||||
game.wildCard = 'J'
|
game.wildCard = 'J'
|
||||||
product2 := calcProduct(game)
|
product2 := calcProduct(game)
|
||||||
|
|
||||||
return product1, product2
|
return result{product1, product2}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var cardTypes1 = []rune{'A', 'K', 'Q', 'J', 'T', '9', '8', '7', '6', '5', '4', '3', '2'}
|
var cardTypes1 = []rune{'A', 'K', 'Q', 'J', 'T', '9', '8', '7', '6', '5', '4', '3', '2'}
|
||||||
|
|
|
@ -54,19 +54,21 @@ func TestExample(t *testing.T) {
|
||||||
is := is.New(t)
|
is := is.New(t)
|
||||||
scan := bufio.NewScanner(bytes.NewReader(example))
|
scan := bufio.NewScanner(bytes.NewReader(example))
|
||||||
|
|
||||||
score1, score2 := run(scan)
|
r, err := run(scan)
|
||||||
is.Equal(score1, uint64(6440))
|
is.NoErr(err)
|
||||||
is.Equal(score2, uint64(5905))
|
is.Equal(r.valuePT1, uint64(6440))
|
||||||
|
is.Equal(r.valuePT2, uint64(5905))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSolution(t *testing.T) {
|
func TestSolution(t *testing.T) {
|
||||||
is := is.New(t)
|
is := is.New(t)
|
||||||
scan := bufio.NewScanner(bytes.NewReader(input))
|
scan := bufio.NewScanner(bytes.NewReader(input))
|
||||||
|
|
||||||
score1, score2 := run(scan)
|
r, err := run(scan)
|
||||||
t.Log("score1", score1)
|
is.NoErr(err)
|
||||||
is.Equal(score1, uint64(248559379))
|
t.Log("score1", r.valuePT1)
|
||||||
|
is.Equal(r.valuePT1, uint64(248559379))
|
||||||
|
|
||||||
t.Log("score2", score2)
|
t.Log("score2", r.valuePT2)
|
||||||
is.Equal(score2, uint64(249631254))
|
is.Equal(r.valuePT2, uint64(249631254))
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,11 +28,6 @@ func run(scan *bufio.Scanner) (*result, error) {
|
||||||
text := scan.Text()
|
text := scan.Text()
|
||||||
m.readLine(text)
|
m.readLine(text)
|
||||||
}
|
}
|
||||||
// solution9 := m.expand(9).sumPaths()
|
|
||||||
// fmt.Println(solution9)
|
|
||||||
|
|
||||||
// solution99 := m.expand(99).sumPaths()
|
|
||||||
// fmt.Println(solution99)
|
|
||||||
|
|
||||||
return &result{
|
return &result{
|
||||||
valuePT1: m.expand(1).sumPaths(),
|
valuePT1: m.expand(1).sumPaths(),
|
||||||
|
@ -69,8 +64,8 @@ func (m *Map) String() string {
|
||||||
n = n.Next()
|
n = n.Next()
|
||||||
}
|
}
|
||||||
|
|
||||||
for row:=0; row<m.rows; row++ {
|
for row := 0; row < m.rows; row++ {
|
||||||
for col:=0; col<m.cols; col++ {
|
for col := 0; col < m.cols; col++ {
|
||||||
if n := m.getRC(row, col); n != nil {
|
if n := m.getRC(row, col); n != nil {
|
||||||
buf.WriteRune('#')
|
buf.WriteRune('#')
|
||||||
} else {
|
} else {
|
||||||
|
@ -150,7 +145,7 @@ func (m *Map) expand(rate int) *Map {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if n := m.getRC(row, col); n!= nil {
|
if n := m.getRC(row, col); n != nil {
|
||||||
newM.Add('#', fromXY(offsetC+col, offsetR+row, newM.cols))
|
newM.Add('#', fromXY(offsetC+col, offsetR+row, newM.cols))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,7 +153,7 @@ func (m *Map) expand(rate int) *Map {
|
||||||
|
|
||||||
return newM
|
return newM
|
||||||
}
|
}
|
||||||
func(m *Map) sumPaths() int {
|
func (m *Map) sumPaths() int {
|
||||||
var positions []int
|
var positions []int
|
||||||
|
|
||||||
n := m.Head()
|
n := m.Head()
|
||||||
|
@ -170,21 +165,22 @@ func(m *Map) sumPaths() int {
|
||||||
var paths []int
|
var paths []int
|
||||||
|
|
||||||
for i := 0; i < len(positions); i++ {
|
for i := 0; i < len(positions); i++ {
|
||||||
p:= positions[i]
|
p := positions[i]
|
||||||
pXY := toXY(p, m.cols)
|
pXY := toXY(p, m.cols)
|
||||||
|
|
||||||
for j := i; j < len(positions); j++ {
|
for j := i; j < len(positions); j++ {
|
||||||
c := positions[j]
|
c := positions[j]
|
||||||
if c == p { continue }
|
if c == p {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
cXY := toXY(c, m.cols)
|
cXY := toXY(c, m.cols)
|
||||||
|
|
||||||
path := abs(cXY[0]-pXY[0])+abs(cXY[1]-pXY[1])
|
path := aoc.ABS(cXY[0]-pXY[0]) + aoc.ABS(cXY[1]-pXY[1])
|
||||||
paths = append(paths, path)
|
paths = append(paths, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return sum(paths...)
|
return aoc.Sum(paths...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func all(m map[int]bool) []int {
|
func all(m map[int]bool) []int {
|
||||||
|
@ -198,17 +194,4 @@ func all(m map[int]bool) []int {
|
||||||
return lis
|
return lis
|
||||||
}
|
}
|
||||||
func fromXY(x, y, w int) int { return y*w + x }
|
func fromXY(x, y, w int) int { return y*w + x }
|
||||||
func toXY(i, w int) []int { return []int{i % w, i / w} }
|
func toXY(i, w int) [2]int { return [2]int{i % w, i / w} }
|
||||||
func abs(i int) int {
|
|
||||||
if i < 0 {
|
|
||||||
return -i
|
|
||||||
}
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
func sum(arr ...int) int {
|
|
||||||
acc :=0
|
|
||||||
for _, a := range arr {
|
|
||||||
acc += a
|
|
||||||
}
|
|
||||||
return acc
|
|
||||||
}
|
|
||||||
|
|
59
tools.go
59
tools.go
|
@ -183,7 +183,7 @@ func (l *List[T]) add(a *Node[T]) {
|
||||||
func (l *List[T]) Get(pos int) *Node[T] {
|
func (l *List[T]) Get(pos int) *Node[T] {
|
||||||
return l.p[pos]
|
return l.p[pos]
|
||||||
}
|
}
|
||||||
func(l *List[T]) GetN(pos ...int) []*Node[T] {
|
func (l *List[T]) GetN(pos ...int) []*Node[T] {
|
||||||
lis := make([]*Node[T], len(pos))
|
lis := make([]*Node[T], len(pos))
|
||||||
for i, p := range pos {
|
for i, p := range pos {
|
||||||
lis[i] = l.p[p]
|
lis[i] = l.p[p]
|
||||||
|
@ -193,3 +193,60 @@ func(l *List[T]) GetN(pos ...int) []*Node[T] {
|
||||||
func (l *List[T]) Head() *Node[T] {
|
func (l *List[T]) Head() *Node[T] {
|
||||||
return l.head
|
return l.head
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SliceMap[T, U any](fn func(T) U, in ...T) []U {
|
||||||
|
lis := make([]U, len(in))
|
||||||
|
for i := range lis {
|
||||||
|
lis[i] = fn(in[i])
|
||||||
|
}
|
||||||
|
return lis
|
||||||
|
}
|
||||||
|
func SliceIMap[T, U any](fn func(int, T) U, in ...T) []U {
|
||||||
|
lis := make([]U, len(in))
|
||||||
|
for i := range lis {
|
||||||
|
lis[i] = fn(i, in[i])
|
||||||
|
}
|
||||||
|
return lis
|
||||||
|
}
|
||||||
|
|
||||||
|
func Atoi(s string) int {
|
||||||
|
i, _ := strconv.Atoi(s)
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
func Repeat(s string, i int) []string {
|
||||||
|
lis := make([]string, i)
|
||||||
|
for i := range lis {
|
||||||
|
lis[i] = s
|
||||||
|
}
|
||||||
|
return lis
|
||||||
|
}
|
||||||
|
|
||||||
|
func Sum[T integer](arr ...T) T {
|
||||||
|
var acc T
|
||||||
|
for _, a := range arr {
|
||||||
|
acc += a
|
||||||
|
}
|
||||||
|
return acc
|
||||||
|
}
|
||||||
|
func SumFunc[T any,U integer](fn func(T) U, input ...T) U {
|
||||||
|
return Sum(SliceMap(fn, input...)...)
|
||||||
|
}
|
||||||
|
func SumIFunc[T any,U integer](fn func(int, T) U, input ...T) U {
|
||||||
|
return Sum(SliceIMap(fn, input...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Power2(n int) int {
|
||||||
|
p := 2
|
||||||
|
for ; n > 1; n-- {
|
||||||
|
p *= 2
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func ABS(i int) int {
|
||||||
|
if i < 0 {
|
||||||
|
return -i
|
||||||
|
}
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user