Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
twitch
live-coding-fr
Commits
0fbb81e4
Commit
0fbb81e4
authored
Apr 26, 2021
by
Colin DAMON
Browse files
Game of life part 2
parent
e8e8cf09
Changes
7
Hide whitespace changes
Inline
Side-by-side
game-of-life/src/main/java/fr/ippon/life/Cell.java
View file @
0fbb81e4
...
...
@@ -2,24 +2,16 @@ package fr.ippon.life;
import
java.util.Set
;
public
class
Cell
{
public
record
Cell
(
int
row
,
int
column
)
{
private
static
final
int
LOW_POPULATION_THRESHOLD
=
2
;
private
static
final
int
HIGH_POPULATION_THRESHOLD
=
3
;
private
static
final
int
BORN_THRESHOLD
=
HIGH_POPULATION_THRESHOLD
;
private
final
int
row
;
private
final
int
column
;
public
Cell
(
int
row
,
int
column
)
{
this
.
row
=
row
;
this
.
column
=
column
;
}
boolean
stayAlive
(
Set
<
Cell
>
aliveCells
)
{
long
neighbourgCount
=
countNeigbours
(
aliveCells
);
return
neighbourgCount
==
LOW_POPULATION_THRESHOLD
||
neighbourgCount
==
HIGH_POPULATION_THRESHOLD
;
return
neighbourgCount
==
LOW_POPULATION_THRESHOLD
||
neighbourgCount
==
HIGH_POPULATION_THRESHOLD
;
}
boolean
born
(
Set
<
Cell
>
aliveCells
)
{
...
...
@@ -27,7 +19,9 @@ public class Cell {
}
private
long
countNeigbours
(
Set
<
Cell
>
aliveCells
)
{
return
aliveCells
.
stream
().
filter
(
this
::
isNeighbour
).
count
();
return
aliveCells
.
stream
()
.
filter
(
this
::
isNeighbour
)
.
count
();
}
private
boolean
isNeighbour
(
Cell
other
)
{
...
...
@@ -35,38 +29,11 @@ public class Cell {
return
false
;
}
return
delta
(
row
,
other
.
row
)
<=
1
&&
delta
(
column
,
other
.
column
)
<=
1
;
return
delta
(
row
,
other
.
row
)
<=
1
&&
delta
(
column
,
other
.
column
)
<=
1
;
}
private
static
int
delta
(
int
first
,
int
second
)
{
return
Math
.
abs
(
first
-
second
);
}
public
int
getRow
()
{
return
row
;
}
public
int
getColumn
()
{
return
column
;
}
@Override
public
int
hashCode
()
{
final
int
prime
=
31
;
int
result
=
1
;
result
=
prime
*
result
+
column
;
result
=
prime
*
result
+
row
;
return
result
;
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
return
true
;
if
(
obj
==
null
)
return
false
;
if
(
getClass
()
!=
obj
.
getClass
())
return
false
;
Cell
other
=
(
Cell
)
obj
;
if
(
column
!=
other
.
column
)
return
false
;
if
(
row
!=
other
.
row
)
return
false
;
return
true
;
}
}
game-of-life/src/main/java/fr/ippon/life/Grid.java
View file @
0fbb81e4
...
...
@@ -9,55 +9,77 @@ import java.util.stream.Stream;
public
class
Grid
{
private
final
Set
<
Cell
>
deadCells
;
private
final
Box
bo
x
;
private
final
Box
bo
rder
;
Grid
(
Set
<
Cell
>
c
ells
)
{
box
=
new
Box
(
c
ells
);
this
.
deadCells
=
buildDeadCells
(
c
ells
);
Grid
(
Set
<
Cell
>
aliveC
ells
)
{
this
.
deadCells
=
buildDeadCells
(
aliveC
ells
);
border
=
new
Box
(
aliveC
ells
);
}
private
Set
<
Cell
>
buildDeadCells
(
Set
<
Cell
>
cells
)
{
return
IntStream
.
range
(
box
.
getTopRow
(),
box
.
getBottomRow
())
.
mapToObj
(
Integer:
:
valueOf
)
.
flatMap
(
row
->
toDeadCell
(
cells
,
row
))
private
Set
<
Cell
>
buildDeadCells
(
Set
<
Cell
>
aliveCells
)
{
return
aliveCells
.
stream
()
.
map
(
Box:
:
new
)
.
flatMap
(
Box:
:
cells
)
.
filter
(
cell
->
!
aliveCells
.
contains
(
cell
))
.
collect
(
Collectors
.
toUnmodifiableSet
());
}
private
Stream
<
Cell
>
toDeadCell
(
Set
<
Cell
>
cells
,
int
row
)
{
return
IntStream
.
range
(
box
.
getLeftColumn
(),
box
.
getRightColumn
())
.
mapToObj
(
column
->
new
Cell
(
row
,
column
))
.
filter
(
cell
->
!
cells
.
contains
(
cell
));
}
public
Collection
<
Cell
>
deadCells
()
{
return
deadCells
;
}
public
int
leftColumn
()
{
return
border
.
leftColumn
();
}
public
int
rightColumn
()
{
return
border
.
rightColumn
();
}
public
int
topRow
()
{
return
border
.
topRow
();
}
public
int
bottomRow
()
{
return
border
.
bottomRow
();
}
private
static
class
Box
{
private
final
Point
topLeft
;
private
final
Point
bottomRight
;
public
Box
(
Cell
cell
)
{
this
(
Set
.
of
(
cell
));
}
public
Box
(
Set
<
Cell
>
cells
)
{
topLeft
=
Point
.
topLeft
(
cells
);
bottomRight
=
Point
.
bottomRight
(
cells
);
}
public
int
getTopRow
()
{
private
Stream
<
Cell
>
cells
()
{
return
IntStream
.
range
(
leftColumn
(),
rightColumn
()).
mapToObj
(
Integer:
:
valueOf
).
flatMap
(
column
->
cellsColumn
(
column
));
}
private
Stream
<
Cell
>
cellsColumn
(
Integer
column
)
{
return
IntStream
.
range
(
topRow
(),
bottomRow
()).
mapToObj
(
Integer:
:
valueOf
).
map
(
row
->
new
Cell
(
row
,
column
));
}
public
int
topRow
()
{
return
topLeft
.
getRow
();
}
public
int
getB
ottomRow
()
{
public
int
b
ottomRow
()
{
return
bottomRight
.
getRow
()
+
1
;
}
public
int
getL
eftColumn
()
{
public
int
l
eftColumn
()
{
return
topLeft
.
getColumn
();
}
public
int
getR
ightColumn
()
{
public
int
r
ightColumn
()
{
return
bottomRight
.
getColumn
()
+
1
;
}
}
...
...
@@ -73,17 +95,17 @@ public class Grid {
}
private
static
Point
topLeft
(
Set
<
Cell
>
cells
)
{
int
row
=
cells
.
stream
().
mapToInt
(
Cell:
:
getR
ow
).
min
().
orElse
(
0
);
int
row
=
cells
.
stream
().
mapToInt
(
Cell:
:
r
ow
).
min
().
orElse
(
0
);
int
column
=
cells
.
stream
().
mapToInt
(
Cell:
:
getC
olumn
).
min
().
orElse
(
0
);
int
column
=
cells
.
stream
().
mapToInt
(
Cell:
:
c
olumn
).
min
().
orElse
(
0
);
return
new
Point
(
row
-
1
,
column
-
1
);
}
private
static
Point
bottomRight
(
Set
<
Cell
>
cells
)
{
int
row
=
cells
.
stream
().
mapToInt
(
Cell:
:
getR
ow
).
max
().
orElse
(
0
);
int
row
=
cells
.
stream
().
mapToInt
(
Cell:
:
r
ow
).
max
().
orElse
(
0
);
int
column
=
cells
.
stream
().
mapToInt
(
Cell:
:
getC
olumn
).
max
().
orElse
(
0
);
int
column
=
cells
.
stream
().
mapToInt
(
Cell:
:
c
olumn
).
max
().
orElse
(
0
);
return
new
Point
(
row
+
1
,
column
+
1
);
}
...
...
game-of-life/src/main/java/fr/ippon/life/Renderer.java
0 → 100644
View file @
0fbb81e4
package
fr.ippon.life
;
public
interface
Renderer
<
T
>
{
T
run
(
Grid
grid
);
}
game-of-life/src/main/java/fr/ippon/life/StringRenderer.java
0 → 100644
View file @
0fbb81e4
package
fr.ippon.life
;
import
java.util.function.IntFunction
;
import
java.util.stream.Collectors
;
import
java.util.stream.IntStream
;
public
class
StringRenderer
implements
Renderer
<
String
>
{
@Override
public
String
run
(
Grid
grid
)
{
return
new
GridRenderer
(
grid
).
run
();
}
private
static
class
GridRenderer
{
private
final
Grid
grid
;
private
GridRenderer
(
Grid
grid
)
{
this
.
grid
=
grid
;
}
private
String
run
()
{
return
IntStream
.
range
(
grid
.
topRow
(),
grid
.
bottomRow
())
.
mapToObj
(
Integer:
:
valueOf
)
.
map
(
row
->
rowRepresentation
(
grid
,
row
))
.
collect
(
Collectors
.
joining
(
System
.
lineSeparator
(),
""
,
System
.
lineSeparator
()));
}
private
String
rowRepresentation
(
Grid
grid
,
Integer
row
)
{
return
IntStream
.
range
(
grid
.
leftColumn
(),
grid
.
rightColumn
()).
mapToObj
(
cellRepresentation
(
row
)).
collect
(
Collectors
.
joining
());
}
private
IntFunction
<
String
>
cellRepresentation
(
Integer
row
)
{
return
column
->
{
if
(
aliveCell
(
row
,
column
))
{
return
"o"
;
}
return
"x"
;
};
}
private
boolean
aliveCell
(
Integer
row
,
int
column
)
{
return
!
grid
.
deadCells
().
contains
(
new
Cell
(
row
,
column
));
}
}
}
game-of-life/src/test/java/fr/ippon/life/GameOfLifeTest.java
View file @
0fbb81e4
...
...
@@ -39,20 +39,20 @@ class GameOfLifeTest {
@Test
void
nextGenerationShouldHaveOneColumnFromOneLine
()
{
Generation
nextGeneration
=
new
Generation
(
cell
(
4
,
5
),
cell
(
5
,
5
),
cell
(
6
,
5
)
).
next
();
Generation
nextGeneration
=
threeCellsColumn
(
).
next
();
assertThat
(
nextGeneration
.
getAliveCells
()).
containsExactlyInAnyOrder
(
cell
(
5
,
4
),
cell
(
5
,
5
),
cell
(
5
,
6
));
}
@Test
void
shouldAdvanceInGenerations
()
{
Generation
nextGeneration
=
threeCellsColumn
();
Generation
nextGeneration
=
threeCellsColumn
()
.
next
().
next
()
;
assertThat
(
nextGeneration
.
getAliveCells
()).
containsExactlyInAnyOrder
(
cell
(
4
,
5
),
cell
(
5
,
5
),
cell
(
6
,
5
));
}
private
Generation
threeCellsColumn
()
{
return
new
Generation
(
cell
(
4
,
5
),
cell
(
5
,
5
),
cell
(
6
,
5
))
.
next
().
next
()
;
return
new
Generation
(
cell
(
4
,
5
),
cell
(
5
,
5
),
cell
(
6
,
5
));
}
private
static
Cell
cell
(
int
row
,
int
column
)
{
...
...
game-of-life/src/test/java/fr/ippon/life/StringRendererUnitTest.java
0 → 100644
View file @
0fbb81e4
package
fr.ippon.life
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.*;
import
java.util.Arrays
;
import
java.util.HashSet
;
import
java.util.Set
;
import
java.util.stream.Collectors
;
import
org.junit.jupiter.api.Test
;
class
StringRendererUnitTest
{
private
static
final
StringRenderer
renderer
=
new
StringRenderer
();
@Test
void
shouldDisplayGridWithOneAliveCell
()
{
assertThat
(
renderer
.
run
(
grid
().
alive
(
1
,
1
).
build
())).
isEqualTo
(
join
(
"xxx"
,
"xox"
,
"xxx"
));
}
@Test
void
shouldDisplayGridWithTwoAliveCell
()
{
assertThat
(
renderer
.
run
(
grid
().
alive
(
1
,
1
).
alive
(
1
,
3
).
build
())).
isEqualTo
(
join
(
"xxxxx"
,
"xoxox"
,
"xxxxx"
));
}
private
static
String
join
(
String
...
parts
)
{
return
Arrays
.
stream
(
parts
).
collect
(
Collectors
.
joining
(
System
.
lineSeparator
(),
""
,
System
.
lineSeparator
()));
}
private
GridBuilder
grid
()
{
return
new
GridBuilder
();
}
private
static
class
GridBuilder
{
private
final
Set
<
Cell
>
cells
=
new
HashSet
<>();
public
GridBuilder
alive
(
int
row
,
int
column
)
{
cells
.
add
(
new
Cell
(
row
,
column
));
return
this
;
}
public
Grid
build
()
{
return
new
Grid
(
cells
);
}
}
}
package-lock.json
View file @
0fbb81e4
...
...
@@ -1276,8 +1276,7 @@
"isexe"
:
{
"version"
:
"2.0.0"
,
"resolved"
:
"https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz"
,
"integrity"
:
"sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
,
"dev"
:
true
"integrity"
:
"sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
},
"isobject"
:
{
"version"
:
"3.0.1"
,
...
...
@@ -2093,6 +2092,66 @@
"java-parser"
:
"1.0.2"
,
"lodash"
:
"4.17.21"
,
"prettier"
:
"2.2.1"
},
"dependencies"
:
{
"mimic-fn"
:
{
"version"
:
"2.1.0"
,
"resolved"
:
"https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz"
,
"integrity"
:
"sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
},
"npm-run-path"
:
{
"version"
:
"4.0.1"
,
"resolved"
:
"https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz"
,
"integrity"
:
"sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw=="
,
"requires"
:
{
"path-key"
:
"^3.0.0"
}
},
"onetime"
:
{
"version"
:
"5.1.2"
,
"resolved"
:
"https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz"
,
"integrity"
:
"sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="
,
"requires"
:
{
"mimic-fn"
:
"^2.1.0"
}
},
"path-key"
:
{
"version"
:
"3.1.1"
,
"resolved"
:
"https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz"
,
"integrity"
:
"sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
},
"prettier"
:
{
"version"
:
"2.2.1"
,
"resolved"
:
"https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz"
,
"integrity"
:
"sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q=="
,
"dev"
:
true
},
"shebang-command"
:
{
"version"
:
"2.0.0"
,
"resolved"
:
"https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz"
,
"integrity"
:
"sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="
,
"requires"
:
{
"shebang-regex"
:
"^3.0.0"
}
},
"shebang-regex"
:
{
"version"
:
"3.0.0"
,
"resolved"
:
"https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz"
,
"integrity"
:
"sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
},
"supports-color"
:
{
"version"
:
"7.2.0"
,
"resolved"
:
"https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz"
,
"integrity"
:
"sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="
},
"which"
:
{
"version"
:
"2.0.2"
,
"resolved"
:
"https://registry.npmjs.org/which/-/which-2.0.2.tgz"
,
"integrity"
:
"sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="
,
"requires"
:
{
"isexe"
:
"^2.0.0"
}
}
}
},
"pretty-quick"
:
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment