update
parent
8128450d54
commit
44b67f0de4
@ -0,0 +1,23 @@
|
|||||||
|
package q04
|
||||||
|
|
||||||
|
func waterCorners(grid [][]rune, x, y int) int {
|
||||||
|
isWater := func(x, y int) int {
|
||||||
|
if x < 0 || y < 0 || x >= len(grid) || y >= len(grid[x]) || grid[x][y] == ' ' {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return isWater(x-1, y) + isWater(x+1, y) + isWater(x, y-1) + isWater(x, y+1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func solveP1(grid [][]rune) int {
|
||||||
|
var ps int
|
||||||
|
for x := range grid {
|
||||||
|
for y := range grid[x] {
|
||||||
|
if waterCorners(grid, x, y) == 3 {
|
||||||
|
ps++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ps
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package q04
|
||||||
|
|
||||||
|
func check(x, y, n, m int) bool {
|
||||||
|
return x >= 0 && y >= 0 && x < n && y < m
|
||||||
|
}
|
||||||
|
|
||||||
|
var dirs = [][]int{{-1, 0}, {0, -1}, {1, 0}, {0, 1}}
|
||||||
|
|
||||||
|
func dfs(grid [][]rune, vis [][]bool, x, y, n, m int) {
|
||||||
|
if !check(x, y, n, m) || grid[x][y] == ' ' || vis[x][y] {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
vis[x][y] = true
|
||||||
|
for _, d := range dirs {
|
||||||
|
x1, y1 := x+d[0], y+d[1]
|
||||||
|
dfs(grid, vis, x1, y1, n, m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func solveP2(grid [][]rune) int {
|
||||||
|
var res int
|
||||||
|
n := len(grid)
|
||||||
|
m := len(grid[0])
|
||||||
|
vis := make([][]bool, n)
|
||||||
|
for i := range vis {
|
||||||
|
vis[i] = make([]bool, m)
|
||||||
|
}
|
||||||
|
for i := range grid {
|
||||||
|
for j := range grid[i] {
|
||||||
|
if !vis[i][j] && grid[i][j] == 'X' {
|
||||||
|
res++
|
||||||
|
dfs(grid, vis, i, j, n, m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
@ -0,0 +1,108 @@
|
|||||||
|
package q04
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/hhhapz/codequest/models"
|
||||||
|
"github.com/hhhapz/codequest/question"
|
||||||
|
)
|
||||||
|
|
||||||
|
type boolgen struct {
|
||||||
|
src *rand.Rand
|
||||||
|
cache int64
|
||||||
|
remaining int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *boolgen) Bool() bool {
|
||||||
|
if b.remaining == 0 {
|
||||||
|
b.cache, b.remaining = b.src.Int63(), 63
|
||||||
|
}
|
||||||
|
|
||||||
|
result := b.cache&0x01 == 1
|
||||||
|
b.cache >>= 1
|
||||||
|
b.remaining--
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
t := template.New("island")
|
||||||
|
var err error
|
||||||
|
t, err = t.Parse(q03Text)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
question.Register(
|
||||||
|
&question.Question{
|
||||||
|
ID: "island",
|
||||||
|
Name: "Island Analysis",
|
||||||
|
Text: t,
|
||||||
|
Level: question.Level2,
|
||||||
|
Generate: func(u *models.User) string {
|
||||||
|
inp := generate(u)
|
||||||
|
res := make([]string, 0, rows)
|
||||||
|
|
||||||
|
for _, row := range inp {
|
||||||
|
res = append(res, string(row))
|
||||||
|
}
|
||||||
|
return strings.Join(res, "\n")
|
||||||
|
},
|
||||||
|
Validate: func(u *models.User, part question.Part, solution string) bool {
|
||||||
|
return Validate(u, part, solution)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
rows = 90
|
||||||
|
cols = 50
|
||||||
|
)
|
||||||
|
|
||||||
|
func generate(u *models.User) [][]rune {
|
||||||
|
res := make([][]rune, rows)
|
||||||
|
|
||||||
|
b := boolgen{
|
||||||
|
src: question.UserRandom(u),
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < rows; i++ {
|
||||||
|
res[i] = make([]rune, cols)
|
||||||
|
for j := 0; j < cols; j++ {
|
||||||
|
m := 'X'
|
||||||
|
if b.Bool() {
|
||||||
|
m = ' '
|
||||||
|
}
|
||||||
|
res[i][j] = m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func Validate(u *models.User, p question.Part, sol string) bool {
|
||||||
|
inp := generate(u)
|
||||||
|
|
||||||
|
var n int
|
||||||
|
switch p {
|
||||||
|
case question.Part1:
|
||||||
|
n = solveP1(inp)
|
||||||
|
case question.Part2:
|
||||||
|
n = solveP2(inp)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("submitted", u.Name, p, sol)
|
||||||
|
fmt.Println("actual", u.Name, p, n)
|
||||||
|
|
||||||
|
return strconv.Itoa(n) == sol
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:embed q04.md
|
||||||
|
var q03Text string
|
@ -0,0 +1,107 @@
|
|||||||
|
You decide to visit the archipelagos of Indonesia. You find a map of the area near South Sulawesi,
|
||||||
|
and can see where there is land (marked with an `X`), and where the ocean is (empty space).
|
||||||
|
|
||||||
|
You and your friends decide you want to stay at the islands for the weekend.
|
||||||
|
|
||||||
|
However, there are so many islands to pick from, and you have no way to decide which one to pick to
|
||||||
|
stay at. To make a decision, you come up with a plan.
|
||||||
|
|
||||||
|
Firstly, you have decided that the location needs to be a peninsula. That means, water on 3 sides,
|
||||||
|
and land on one side.
|
||||||
|
|
||||||
|
### Note:
|
||||||
|
|
||||||
|
> When counting peninsulas, do not consider diagonal tiles. Only consider those directly to the left,
|
||||||
|
> right, above and below the tile.
|
||||||
|
|
||||||
|
> The (invisible) edges of the input all count after the water tiles.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
Given the following input:
|
||||||
|
|
||||||
|
```
|
||||||
|
ABCDE
|
||||||
|
1. X XX
|
||||||
|
2. X X
|
||||||
|
3. X
|
||||||
|
4. XX X
|
||||||
|
```
|
||||||
|
|
||||||
|
Contains 4 peninsulas:
|
||||||
|
|
||||||
|
* 1D
|
||||||
|
* 3D
|
||||||
|
* 4A
|
||||||
|
* 4B
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Given the following input:
|
||||||
|
|
||||||
|
```
|
||||||
|
ABCDEFGH
|
||||||
|
1 XXX XX
|
||||||
|
2 X XX X
|
||||||
|
3 XXXXX X
|
||||||
|
4 X X
|
||||||
|
5 X XXXX
|
||||||
|
6 XX XXXX
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Contains 9 peninsulas:
|
||||||
|
|
||||||
|
* 1C
|
||||||
|
* 1H
|
||||||
|
* 2B
|
||||||
|
* 3A
|
||||||
|
* 4D
|
||||||
|
* 5A
|
||||||
|
* 5H
|
||||||
|
* 6B
|
||||||
|
* 6D
|
||||||
|
|
||||||
|
To get the answer for part one, **what is the total number of peninsulas you can count on your
|
||||||
|
map?**
|
||||||
|
|
||||||
|
{{ if .Part1.Completed -}}
|
||||||
|
|
||||||
|
**Congratulations! You got Part 1 correct. Your answer was `{{ .Part1.Solution }}`.**
|
||||||
|
|
||||||
|
## Part 2
|
||||||
|
|
||||||
|
With the number of peninsulas that are in the lake, you are having trouble determining which one to
|
||||||
|
pick. In order to do so, you have devised a plan to try to see which island has the most number of
|
||||||
|
peninsulas.
|
||||||
|
|
||||||
|
In order to do this, though, we first need to count how many islands we have.
|
||||||
|
|
||||||
|
An island is a contiguous set of grids, that are connected by water in at least one of the four
|
||||||
|
directions, similar to a peninsula.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
Given the following input:
|
||||||
|
|
||||||
|
```
|
||||||
|
ABCDEFGH
|
||||||
|
1 XXX XX
|
||||||
|
2 X XX X
|
||||||
|
3 XXXXX X
|
||||||
|
4 X X
|
||||||
|
5 X XXXX
|
||||||
|
6 XX XXXX
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
There are 3 distinct islands.
|
||||||
|
|
||||||
|
**What is the total number of islands in your map?**
|
||||||
|
|
||||||
|
{{ if .Part2.Completed -}}
|
||||||
|
|
||||||
|
**Congratulations! You have completed both parts! The answer was `{{ .Part2.Solution }}`.**
|
||||||
|
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
@ -0,0 +1,43 @@
|
|||||||
|
package q04
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hhhapz/codequest/models"
|
||||||
|
"github.com/hhhapz/codequest/question"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestQ04(t *testing.T) {
|
||||||
|
u := &models.User{
|
||||||
|
ID: "123",
|
||||||
|
}
|
||||||
|
|
||||||
|
q := question.QuestionByID("island")
|
||||||
|
|
||||||
|
raw := q.Generate(u)
|
||||||
|
|
||||||
|
t.Logf("INPUT:\n\n%s\n\n", raw)
|
||||||
|
|
||||||
|
input := make([][]rune, 0, rows)
|
||||||
|
|
||||||
|
for _, row := range strings.Split(raw, "\n") {
|
||||||
|
input = append(input, []rune(row))
|
||||||
|
}
|
||||||
|
|
||||||
|
// res := solveP1(input)
|
||||||
|
// t.Logf("part 1 result: %d", res)
|
||||||
|
// if !q.Validate(u, question.Part1, strconv.Itoa(res)) {
|
||||||
|
// t.Errorf("Expected question 1 part 1(%v) to be correct!", res)
|
||||||
|
// }
|
||||||
|
|
||||||
|
res := solveP2(input)
|
||||||
|
if !q.Validate(u, question.Part2, strconv.Itoa(res)) {
|
||||||
|
t.Errorf("Expected question 2 part 2(%v) to be correct!", res)
|
||||||
|
}
|
||||||
|
|
||||||
|
if q.Validate(u, question.Part1, "") {
|
||||||
|
t.Errorf("Expected bad input to be invalid")
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package q05
|
||||||
|
|
||||||
|
func solveP1(nums []int) int {
|
||||||
|
var sum int
|
||||||
|
for _, v := range nums {
|
||||||
|
sum += int(float64(v)/2.5 - 2)
|
||||||
|
}
|
||||||
|
return sum
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package q05
|
||||||
|
|
||||||
|
func solveP2(nums []int) int {
|
||||||
|
var sum int
|
||||||
|
for _, v := range nums {
|
||||||
|
fuel := int(float64(v)/2.5 - 2)
|
||||||
|
for fuel > 0 {
|
||||||
|
sum += fuel
|
||||||
|
fuel = int(float64(fuel)/2.5 - 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sum
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
package q05
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/hhhapz/codequest/models"
|
||||||
|
"github.com/hhhapz/codequest/question"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
t := template.New("fuel")
|
||||||
|
var err error
|
||||||
|
t, err = t.Parse(q05Text)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
question.Register(
|
||||||
|
&question.Question{
|
||||||
|
ID: "fuel",
|
||||||
|
Name: "Fuel for the Farlands",
|
||||||
|
Text: t,
|
||||||
|
Level: question.Level1,
|
||||||
|
Generate: func(u *models.User) string {
|
||||||
|
inp := generate(u)
|
||||||
|
nums := make([]string, nums)
|
||||||
|
for i, num := range inp {
|
||||||
|
nums[i] = strconv.Itoa(num)
|
||||||
|
}
|
||||||
|
return strings.Join(nums, "\n")
|
||||||
|
},
|
||||||
|
Validate: func(u *models.User, part question.Part, solution string) bool {
|
||||||
|
return Validate(u, part, solution)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
nums = 350
|
||||||
|
)
|
||||||
|
|
||||||
|
func generate(u *models.User) []int {
|
||||||
|
res := make([]int, nums)
|
||||||
|
|
||||||
|
r := question.UserRandom(u)
|
||||||
|
|
||||||
|
for i := 0; i < nums; i++ {
|
||||||
|
if nums < 10 {
|
||||||
|
res[i] = r.Intn(10000-200) + 200
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
res[i] = r.Intn(1000000-1000) + 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func Validate(u *models.User, p question.Part, sol string) bool {
|
||||||
|
inp := generate(u)
|
||||||
|
|
||||||
|
var n int
|
||||||
|
switch p {
|
||||||
|
case question.Part1:
|
||||||
|
n = solveP1(inp)
|
||||||
|
case question.Part2:
|
||||||
|
n = solveP2(inp)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("submitted", u.Name, p, sol)
|
||||||
|
fmt.Println("actual", u.Name, p, n)
|
||||||
|
return strconv.Itoa(n) == sol
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:embed q05.md
|
||||||
|
var q05Text string
|
@ -0,0 +1,68 @@
|
|||||||
|
The time has arrived and you need to pack things up and say goodbye. You are leaving for the
|
||||||
|
Farlands, and it's.. far!
|
||||||
|
|
||||||
|
You plan to fly solo over the continents to make it to the Farlands. This is the first time you've
|
||||||
|
ever flown for so long, and so you need to prepare a few things before leaving.
|
||||||
|
|
||||||
|
The first order of business is to determine how much fuel you're going to need to reach. To do this,
|
||||||
|
you need the empty mass of your aircraft.
|
||||||
|
|
||||||
|
With the mass, you can calculate the total required fuel.
|
||||||
|
|
||||||
|
For each each mass, the amount of fuel can be calculated using this **formula**. Take the mass,
|
||||||
|
divide it by 2.5, round down the result, and then subtract 2.
|
||||||
|
|
||||||
|
Before taking off, your friends and family have sent you hundreds of gifts, which you plan to take
|
||||||
|
with you. You'll need to know the total amount of fuel needed for your trip.
|
||||||
|
|
||||||
|
Apply the formula for each item (your input), and sum them to get the total requirement.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
For a mass of `18`, divide it by `2.5` and round down to get `7`, then subtract `2` to get `5` as
|
||||||
|
the fuel requirement.
|
||||||
|
|
||||||
|
For a mass of `58`, divide it by `2.5` and round down to get `23`, then subtract `2` to get `21`.
|
||||||
|
|
||||||
|
For `2022`, the requirement is `806`
|
||||||
|
|
||||||
|
For `84942`, the requirement is `33974`
|
||||||
|
|
||||||
|
**What is the total fuel requirement for your trip?**
|
||||||
|
|
||||||
|
{{ if .Part1.Completed -}}
|
||||||
|
|
||||||
|
**Congratulations! You got Part 1 correct. Your answer was `{{ .Part1.Solution }}`.**
|
||||||
|
|
||||||
|
## Part 2
|
||||||
|
|
||||||
|
Just before you about to take off, your copilot reminded you that you completely forgot to take into
|
||||||
|
account the extra fuel needed for the fuel you already have! Just like your parting gifts, apply the
|
||||||
|
same **formula** on the fuel to obtain the fuel needed for the fuel.
|
||||||
|
|
||||||
|
So, for each gift, calculate the fuel needed, treat that fuel as the mass itself, and calculate the
|
||||||
|
fuel needed, and repeat this process **until** your fuel requirement reaches **zero or a negative
|
||||||
|
value**.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
For a mass of `18`, divide it by `2.5` and round down to get `7`, then subtract `2` to get `5` as
|
||||||
|
the fuel requirement. `5` divided by `2.5` gives you `1`, and subtracting `2` gives you `-1` so the
|
||||||
|
total fuel required is still `5`.
|
||||||
|
|
||||||
|
For a mass of `58`, `21` fuel is used. Then, `21` needs `6` more fuel, and `6` requires no further
|
||||||
|
fuel. The total fuel needed is `21+6 = 27`
|
||||||
|
|
||||||
|
For `2022`, the requirement is `806+320+126+48+17+4 = 1321`
|
||||||
|
|
||||||
|
Using this new formula, **what is the fuel total fuel requirements** for all the mass, but also
|
||||||
|
including the mass of the newly added fuel?
|
||||||
|
|
||||||
|
> Calculate the requirements seperately, and them sum them together for each item.
|
||||||
|
|
||||||
|
{{ if .Part2.Completed -}}
|
||||||
|
|
||||||
|
**Congratulations! You have completed both parts! The answer was `{{ .Part2.Solution }}`.**
|
||||||
|
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
@ -0,0 +1,44 @@
|
|||||||
|
package q05
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hhhapz/codequest/models"
|
||||||
|
"github.com/hhhapz/codequest/question"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestQ05(t *testing.T) {
|
||||||
|
u := &models.User{
|
||||||
|
ID: "123",
|
||||||
|
}
|
||||||
|
|
||||||
|
q := question.QuestionByID("fuel")
|
||||||
|
|
||||||
|
raw := q.Generate(u)
|
||||||
|
|
||||||
|
t.Logf("INPUT:\n\n%s\n\n", raw)
|
||||||
|
|
||||||
|
input := make([]int, 0, nums)
|
||||||
|
|
||||||
|
for _, num := range strings.Split(raw, "\n") {
|
||||||
|
n, _ := strconv.Atoi(num)
|
||||||
|
input = append(input, n)
|
||||||
|
}
|
||||||
|
|
||||||
|
res := solveP1(input)
|
||||||
|
t.Logf("part 1 result: %d", res)
|
||||||
|
if !q.Validate(u, question.Part1, strconv.Itoa(res)) {
|
||||||
|
t.Errorf("Expected question 1 part 1(%v) to be correct!", res)
|
||||||
|
}
|
||||||
|
|
||||||
|
res = solveP2(input)
|
||||||
|
if !q.Validate(u, question.Part2, strconv.Itoa(res)) {
|
||||||
|
t.Errorf("Expected question 2 part 2(%v) to be correct!", res)
|
||||||
|
}
|
||||||
|
|
||||||
|
if q.Validate(u, question.Part1, "") {
|
||||||
|
t.Errorf("Expected bad input to be invalid")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue