Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
A
Advent of Coding
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Christopher Bohn
Advent of Coding
Commits
b552498b
Commit
b552498b
authored
2 years ago
by
Christopher Bohn
Browse files
Options
Downloads
Patches
Plain Diff
Completed Year 2022 Day 11
parent
ea526372
No related branches found
No related tags found
No related merge requests found
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
2022/README.md
+87
-10
87 additions, 10 deletions
2022/README.md
2022/src/main/java/edu/unl/cse/bohn/year2022/Day11.java
+74
-26
74 additions, 26 deletions
2022/src/main/java/edu/unl/cse/bohn/year2022/Day11.java
with
161 additions
and
36 deletions
2022/README.md
+
87
−
10
View file @
b552498b
...
...
@@ -367,27 +367,33 @@ For now, I just need to modify it so that the boredom modification is optional.
Since parts 1 & 2 differ only in whether to use the boredom modification and the number of rounds,
I can create a parameterized method.
###
Possible misinterpretation
###
There's more to it than that
It looks like part 2 isn't saying to abandon the divisor
*now*
to replace the modifier later;
I guess we're supposed to figure out the new modifier for of part 2.
It looks like part 2 isn't saying to abandon the divisor
*now*
to replace the modifier later.
I guess we're supposed to figure out the new modifier for part 2.
That is more interesting, to say the least.
Both the description and my code (without a boredom modifier) agree that after 1 round:
```
Monkey 0 inspected items 2 times.
Monkey 1 inspected items 4 times.
Monkey 2 inspected items 3 times.
Monkey 3 inspected items 6 times.
```
but after 20, the description says
```
Monkey 0 inspected items 99 times.
Monkey 1 inspected items 97 times.
Monkey 2 inspected items 8 times.
Monkey 3 inspected items 103 times.
```
but my code (without a boredom modifier) says
```
Monkey 0 inspected items 96 times.
Monkey 1 inspected items 100 times.
...
...
@@ -395,8 +401,79 @@ Monkey 2 inspected items 7 times.
Monkey 3 inspected items 103 times.
```
I wonder if this suggests the final pre-throw modifier is history based; that is, no modifier on the first inspection,
but then the monkey gets a little bored at something it's seen before.
#### Thought #1
I wonder if what we're seeing suggests the final pre-throw modifier is history based; that is, no modifier on the first
inspection, but then the monkey gets a little bored at something it's seen before. The obvious thing to try is to have
no modification the first time that the monkey inspects an item (preserving the correct result from round 1) and then
divide by 3 if the monkey has seen it before.
No, that isn't it, either. After 20 rounds:
```
Monkey 0 inspected items 96 times.
Monkey 1 inspected items 100 times.
Monkey 2 inspected items 10 times.
Monkey 3 inspected items 102 times.
```
#### Thought #2
It doesn't seem likely that the AOC creator would want us to blindly guess at possible modifications.

Maybe the answer to whether there is
*no*
modifier in part 2 is "both."

Perhaps the hint is in the test for which monkey will receive the item -- it's a test for whether the worry level is
divisible by some value.
We can keep the worry levels down to manageable values while also preserving the outcome of this test
*
for any given
inspection
*
by assigning the worry level to the remainder of that notional division.
Then the remainder is some other value between 0 and the original worry level, which will be the same as the modulus
operator's result (and this remainder will also produce the same modulus result).
How will this affect subsequent throws? All operations are multiplication or addition.
Suppose the original value is $$i = n
\t
imes testDivisor + remainder$$ for some value $$n$$.
In the case of addition, $$i + j = n
\t
imes testDivisor + remainder + j$$ and the resulting modulus is unchanged.
In the case of multiplication, if we view it as repeated addition then the same argument holds.
Either I'm barking up the wrong tree, or we were seeing overflow errors earlier.
```
== After round 20 ==
Monkey 0 inspected items 95 times.
Monkey 1 inspected items 101 times.
Monkey 2 inspected items 9 times.
Monkey 3 inspected items 99 times.
```
Shazbot.
### Thought #3
I'm sure I'm on the right track.
I think I was off-base with my answer to how it will affect subsequent throws.
The problem is that taking the remainder of $$i
\d
iv testDivisor_x$$ might not preserve the modulus of
$$i
\d
iv testDivisor_y$$.
We need to use a divisor that would preserve both -- that is, the divisor must be a multiple of both $$testDivisor_x$$
and $$testDivisor_y$$.
Okay,
*seriously!?*
How does Java not have a least common multiple function?
And let's make the worry levels
`long`
instead of
`int`
just to give us a little more room to grow.
```
== After round 20 ==
Monkey 0 inspected items 99 times.
Monkey 1 inspected items 97 times.
Monkey 2 inspected items 8 times.
Monkey 3 inspected items 103 times.
```
***Shack!***
## Day 12
...
...
This diff is collapsed.
Click to expand it.
2022/src/main/java/edu/unl/cse/bohn/year2022/Day11.java
+
74
−
26
View file @
b552498b
...
...
@@ -43,22 +43,37 @@ public class Day11 extends Puzzle {
@Override
public
long
computePart1
(
List
<
String
>
data
)
{
Monkey
.
setTerse
();
//noinspection MagicNumber
return
measureMonkeyBusiness
(
data
,
20
,
true
);
}
@Override
public
long
computePart2
(
List
<
String
>
data
)
{
Monkey
.
setTerse
();
System
.
out
.
println
(
"== After round 1 =="
);
measureMonkeyBusiness
(
data
,
1
,
false
);
System
.
out
.
println
();
System
.
out
.
println
(
"== After round 20 =="
);
// Monkey.setVerbose();
Monkey
.
setTerse
();
//noinspection MagicNumber
measureMonkeyBusiness
(
data
,
20
,
false
);
System
.
out
.
println
();
System
.
out
.
println
(
"== After round 1000 =="
);
Monkey
.
setTerse
();
// //noinspection MagicNumber
measureMonkeyBusiness
(
data
,
1000
,
false
);
System
.
out
.
println
();
System
.
out
.
println
(
"== After round 10000 =="
);
Monkey
.
setTerse
();
//noinspection MagicNumber
return
measureMonkeyBusiness
(
data
,
2
0
,
false
);
return
measureMonkeyBusiness
(
data
,
1000
0
,
false
);
}
private
static
long
measureMonkeyBusiness
(
List
<
String
>
data
,
int
numberOfRounds
,
boolean
useBoredomModifier
)
{
List
<
Monkey
>
monkeys
=
new
LinkedList
<>();
Monkey
.
clearMonkeys
();
Monkey
.
setTerse
();
if
(
useBoredomModifier
)
{
Monkey
.
setBoredomModification
();
}
else
{
...
...
@@ -76,12 +91,12 @@ public class Day11 extends Puzzle {
}
// Monkey.printMonkeys();
Monkey
.
setVerbose
();
LinkedList
<
Integer
>
inspectionCounts
=
new
LinkedList
<>();
LinkedList
<
Long
>
inspectionCounts
=
new
LinkedList
<>();
for
(
Monkey
monkey
:
monkeys
)
{
inspectionCounts
.
add
(
monkey
.
getNumberOfInspections
());
}
inspectionCounts
.
sort
(
Integer
:
:
compareTo
);
return
(
long
)
inspectionCounts
.
removeLast
()
*
(
long
)
inspectionCounts
.
removeLast
();
inspectionCounts
.
sort
(
Long
:
:
compareTo
);
return
inspectionCounts
.
removeLast
()
*
inspectionCounts
.
removeLast
();
}
private
static
class
Monkey
{
...
...
@@ -89,13 +104,14 @@ public class Day11 extends Puzzle {
private
static
boolean
useBoredomModifier
=
true
;
private
static
boolean
verbose
=
false
;
private
static
final
List
<
Monkey
>
monkeys
=
new
LinkedList
<>();
private
static
int
lcmDivisor
;
private
final
int
monkeyNumber
;
private
final
List
<
Integer
>
items
;
private
final
UnaryOperator
<
Integer
>
worryLevelModifier
;
private
final
List
<
Long
>
items
;
private
final
UnaryOperator
<
Long
>
worryLevelModifier
;
private
final
int
testDivisor
;
private
final
Map
<
Boolean
,
Integer
>
targetMonkeys
;
private
int
inspectionCount
;
private
long
inspectionCount
;
public
static
void
setVerbose
()
{
verbose
=
true
;
...
...
@@ -113,6 +129,26 @@ public class Day11 extends Puzzle {
useBoredomModifier
=
false
;
}
private
static
int
lcm
(
List
<
Integer
>
factors
)
{
return
lcm
(
factors
,
0
);
}
private
static
int
lcm
(
List
<
Integer
>
factors
,
int
index
)
{
// modified from https://www.geeksforgeeks.org/lcm-of-given-array-elements/
// lcm(a,b) = (a*b/gcd(a,b))
if
(
index
==
factors
.
size
()
-
1
)
{
return
factors
.
get
(
index
);
}
int
currentFactor
=
factors
.
get
(
index
);
int
lcmOfRemainingFactors
=
lcm
(
factors
,
index
+
1
);
return
(
currentFactor
*
lcmOfRemainingFactors
/
gcd
(
currentFactor
,
lcmOfRemainingFactors
));
}
private
static
int
gcd
(
int
m
,
int
n
)
{
// modified from https://www.geeksforgeeks.org/lcm-of-given-array-elements/
return
n
==
0
?
m
:
gcd
(
n
,
m
%
n
);
}
public
static
void
printMonkeys
()
{
for
(
Monkey
monkey
:
monkeys
)
{
System
.
out
.
println
(
"Monkey "
+
monkey
.
getMonkeyNumber
()
+
": "
+
monkey
.
getItems
());
...
...
@@ -124,13 +160,13 @@ public class Day11 extends Puzzle {
int
intendedMonkeyNumber
=
Integer
.
parseInt
(
description
.
get
(
0
).
strip
().
split
(
" "
)[
1
].
split
(
":"
)[
0
]);
// > Starting items: 79, 98
String
[]
itemStrings
=
description
.
get
(
1
).
split
(
":"
)[
1
].
strip
().
split
(
", "
);
List
<
Integer
>
items
=
Arrays
.
stream
(
itemStrings
)
.
map
(
Integer
:
:
parse
Int
)
List
<
Long
>
items
=
Arrays
.
stream
(
itemStrings
)
.
map
(
Long
:
:
parse
Long
)
.
collect
(
Collectors
.
toCollection
(
LinkedList:
:
new
));
// > Operation: new = old * 19
String
operator
=
description
.
get
(
2
).
strip
().
split
(
" "
)[
4
];
String
operand
=
description
.
get
(
2
).
strip
().
split
(
" "
)[
5
];
UnaryOperator
<
Integer
>
worryLevelModifier
=
switch
(
operator
)
{
UnaryOperator
<
Long
>
worryLevelModifier
=
switch
(
operator
)
{
case
"+"
->
operand
.
equals
(
"old"
)
?
(
n
->
n
+
n
)
:
(
n
->
n
+
Integer
.
parseInt
(
operand
));
case
"*"
->
operand
.
equals
(
"old"
)
?
(
n
->
n
*
n
)
:
(
n
->
n
*
Integer
.
parseInt
(
operand
));
default
->
throw
new
UnsupportedOperationException
(
"Unhandled operator: "
+
operator
);
...
...
@@ -155,6 +191,8 @@ public class Day11 extends Puzzle {
System
.
out
.
println
(
monkey
);
}
monkeys
.
add
(
monkey
);
List
<
Integer
>
testDivisors
=
monkeys
.
stream
().
map
(
m
->
m
.
testDivisor
).
toList
();
lcmDivisor
=
lcm
(
testDivisors
);
return
monkey
;
}
...
...
@@ -162,7 +200,7 @@ public class Day11 extends Puzzle {
monkeys
.
clear
();
}
private
Monkey
(
List
<
Integer
>
items
,
UnaryOperator
<
Integer
>
worryLevelModifier
,
private
Monkey
(
List
<
Long
>
items
,
UnaryOperator
<
Long
>
worryLevelModifier
,
int
testDivisor
,
Map
<
Boolean
,
Integer
>
targetMonkeys
)
{
this
.
monkeyNumber
=
monkeys
.
size
();
this
.
items
=
items
;
...
...
@@ -176,11 +214,11 @@ public class Day11 extends Puzzle {
return
monkeyNumber
;
}
private
List
<
Integer
>
getItems
()
{
private
List
<
Long
>
getItems
()
{
return
Collections
.
unmodifiableList
(
items
);
}
public
int
getNumberOfInspections
()
{
public
long
getNumberOfInspections
()
{
if
(
verbose
)
{
System
.
out
.
println
(
"Monkey "
+
monkeyNumber
+
" inspected items "
+
inspectionCount
+
" times."
);
}
...
...
@@ -195,9 +233,9 @@ public class Day11 extends Puzzle {
items
.
clear
();
// probably should remove each item in `throwItem()` but that could screw with the iterator
}
private
void
throwItem
(
Integer
item
)
{
private
void
throwItem
(
Long
item
)
{
inspectionCount
++;
int
worryLevel
=
item
;
long
worryLevel
=
item
;
if
(
verbose
)
{
System
.
out
.
println
(
" Monkey inspects an item with a worry level of "
+
worryLevel
+
"."
);
}
...
...
@@ -206,16 +244,9 @@ public class Day11 extends Puzzle {
System
.
out
.
println
(
" Worry level is modified by ("
+
worryLevelModifier
+
") to "
+
worryLevel
+
"."
);
}
worryLevel
=
useBoredomModifier
?
worryLevel
/
BOREDOM_DIVISOR
:
worryLevel
;
worryLevel
=
modifyWorryLevel
(
worryLevel
)
;
boolean
worryLevelIsDivisibleByTestDivisor
=
worryLevel
%
testDivisor
==
0
;
if
(
verbose
)
{
if
(
useBoredomModifier
)
{
System
.
out
.
println
(
" Monkey gets bored with item. Worry level is divided by "
+
BOREDOM_DIVISOR
+
" to "
+
worryLevel
+
"."
);
}
else
{
System
.
out
.
println
(
" Monkey doesn't get bored with item. Worry level remains "
+
worryLevel
+
"."
);
}
System
.
out
.
println
(
" Current worry level is "
+
(
worryLevelIsDivisibleByTestDivisor
?
""
:
"not "
)
+
"divisible by "
+
testDivisor
+
"."
);
...
...
@@ -225,7 +256,24 @@ public class Day11 extends Puzzle {
monkeys
.
get
(
targetMonkeys
.
get
(
worryLevelIsDivisibleByTestDivisor
)).
receiveItem
(
worryLevel
);
}
private
void
receiveItem
(
Integer
item
)
{
private
long
modifyWorryLevel
(
long
worryLevel
)
{
if
(
useBoredomModifier
)
{
worryLevel
=
worryLevel
/
BOREDOM_DIVISOR
;
if
(
verbose
)
{
System
.
out
.
println
(
" Monkey gets bored with item. Worry level is divided by "
+
BOREDOM_DIVISOR
+
" to "
+
worryLevel
+
"."
);
}
}
else
{
worryLevel
=
worryLevel
%
lcmDivisor
;
if
(
verbose
)
{
System
.
out
.
println
(
" Monkey doesn't get bored with item. Worry level is regulated (modulated)"
+
" by "
+
lcmDivisor
+
" to "
+
worryLevel
+
"."
);
}
}
return
worryLevel
;
}
private
void
receiveItem
(
Long
item
)
{
items
.
add
(
item
);
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment