Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
LO21_Pin_Noir_Boucher_Bouri_Detree
CellulutLO21
Commits
feb51b5a
Commit
feb51b5a
authored
May 14, 2021
by
Yann Boucher
Browse files
Implémentation de RLEStructureWriter; Fixed
#37
parent
f5212a32
Pipeline
#77944
passed with stages
in 17 seconds
Changes
7
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
include/coord.hpp
View file @
feb51b5a
...
...
@@ -38,9 +38,9 @@ inline bool operator!=(const Coord& lhs, const Coord& rhs)
//! \brief Comparaison lexicographique de deux coordonnées (pour std::map et compagnie)
inline
bool
operator
<
(
const
Coord
&
lhs
,
const
Coord
&
rhs
)
{
if
(
lhs
.
x
==
rhs
.
x
)
return
lhs
.
y
<
rhs
.
y
;
return
lhs
.
x
<
rhs
.
x
;
if
(
lhs
.
y
==
rhs
.
y
)
return
lhs
.
x
<
rhs
.
x
;
return
lhs
.
y
<
rhs
.
y
;
}
//! \brief Addition de coordonnées
...
...
include/structure.hpp
View file @
feb51b5a
...
...
@@ -16,7 +16,7 @@ Fichier contenant la classe Structure, représentant un ensemble de cellules con
#include
<functional>
#include
<map>
#include
<type_traits>
#include
<
algorithm
>
#include
<
limits
>
#include
"coord.hpp"
...
...
@@ -49,23 +49,34 @@ public:
std
::
is_same
<
typename
std
::
remove_reference
<
decltype
(
*
begin
)
>::
type
,
std
::
pair
<
const
Coord
,
unsigned
>>::
value
,
"Iterator value type must be std::pair<Coord, unsigned>"
);
m_cells
.
clear
();
int
min_x
,
min_y
,
max_x
,
max_y
;
min_x
=
min_y
=
std
::
numeric_limits
<
int
>::
max
();
max_x
=
max_y
=
std
::
numeric_limits
<
int
>::
min
();
// Première passe pour calculer les positions minimales et maximales
for
(
auto
it
=
begin
;
it
!=
end
;
++
it
)
{
// on ignore les entrées avec des cellules zéro, elles sont implicites (cela permet d'économiser pas mal de mémoire)
if
(
it
->
second
==
0
)
continue
;
else
m_cells
[
it
->
first
]
=
it
->
second
;
if
(
it
->
first
.
x
>
max_x
)
max_x
=
it
->
first
.
x
;
if
(
it
->
first
.
x
<
min_x
)
min_x
=
it
->
first
.
x
;
if
(
it
->
first
.
y
>
max_y
)
max_y
=
it
->
first
.
y
;
if
(
it
->
first
.
y
<
min_y
)
min_y
=
it
->
first
.
y
;
}
auto
minmax_width
=
std
::
minmax_element
(
m_cells
.
begin
(),
m_cells
.
end
(),
[](
const
auto
&
a
,
const
auto
&
b
)
{
return
a
.
first
.
x
<
b
.
first
.
x
;
});
m_width
=
minmax_width
.
second
->
first
.
x
-
minmax_width
.
first
->
first
.
x
+
1
;
m_width
=
max_x
-
min_x
+
1
;
m_height
=
max_y
-
min_y
+
1
;
auto
minmax_height
=
std
::
minmax_element
(
m_cells
.
begin
(),
m_cells
.
end
(),
[](
const
auto
&
a
,
const
auto
&
b
)
{
return
a
.
first
.
y
<
b
.
first
.
y
;
});
m_height
=
minmax_height
.
second
->
first
.
y
-
minmax_width
.
first
->
first
.
y
+
1
;
m_cells
.
clear
();
// Seconde passe, on ajoute les éléments avec une position normalisée (élément le plus à gauche <=> x=0, élément le plus en haut <=> y=0)
for
(
auto
it
=
begin
;
it
!=
end
;
++
it
)
{
if
(
it
->
second
==
0
)
continue
;
else
m_cells
[
it
->
first
-
Coord
{
min_x
,
min_y
}]
=
it
->
second
;
}
}
//! \brief Fonction vidant la structure, la laissant vide.
void
clear
()
...
...
@@ -95,17 +106,19 @@ public:
:
m_it
(
it
)
{}
public:
// iterator traits
using
difference_type
=
long
;
using
value_type
=
std
::
pair
<
const
Coord
,
unsigned
>
;
using
pointer
=
const
std
::
pair
<
const
Coord
,
unsigned
>*
;
using
reference
=
const
std
::
pair
<
const
Coord
,
unsigned
>&
;
using
iterator_category
=
std
::
forward_iterator_tag
;
iterator
&
operator
++
()
{
++
m_it
;
return
*
this
;}
iterator
operator
++
(
int
)
{
iterator
retval
=
*
this
;
++
(
*
this
);
return
retval
;}
bool
operator
==
(
iterator
other
)
const
{
return
m_it
==
other
.
m_it
;}
bool
operator
!=
(
iterator
other
)
const
{
return
!
(
*
this
==
other
);}
std
::
pair
<
Coord
,
unsigned
>
operator
*
()
{
return
*
m_it
;}
// iterator traits
using
difference_type
=
long
;
using
value_type
=
std
::
pair
<
Coord
,
unsigned
>
;
using
pointer
=
const
std
::
pair
<
Coord
,
unsigned
>*
;
using
reference
=
const
std
::
pair
<
Coord
,
unsigned
>&
;
using
iterator_category
=
std
::
forward_iterator_tag
;
std
::
pair
<
Coord
,
unsigned
>
operator
*
()
const
{
return
*
m_it
;}
pointer
operator
->
()
const
{
return
&*
m_it
;}
private:
std
::
map
<
Coord
,
unsigned
>::
const_iterator
m_it
;
...
...
include/structurewriter.hpp
View file @
feb51b5a
...
...
@@ -15,7 +15,7 @@ Fichier contenant la classe StructureWrite et ses filles, permettant de sauvegar
#include
<string>
class
S
tructure
;
#include
"s
tructure
.hpp"
//! \class StructureWrite
//! Classe abstraite permettant de sauvegarder une Structure sous différents formats de fichier.
...
...
@@ -37,7 +37,13 @@ public:
virtual
std
::
string
save_structure
(
const
Structure
&
s
)
const
;
private:
std
::
string
state_to_str
(
unsigned
state
);
std
::
string
state_to_str
(
unsigned
state
)
const
;
std
::
string
output_line
(
Structure
::
iterator
&
it
,
Structure
::
iterator
end
)
const
;
std
::
string
output_rle_state
(
Structure
::
iterator
&
it
,
Structure
::
iterator
end
)
const
;
std
::
string
rle
(
const
std
::
string
&
val
,
unsigned
count
)
const
;
private:
mutable
unsigned
m_x
,
m_y
;
};
//! \class JSONStructureWrite
...
...
src/structurewriter.cpp
View file @
feb51b5a
...
...
@@ -42,11 +42,18 @@ std::string RLEStructureWriter::save_structure(const Structure& s) const
result
+=
"x = "
+
std
::
to_string
(
s
.
width
())
+
", "
;
result
+=
"y = "
+
std
::
to_string
(
s
.
height
())
+
"
\n
"
;
// TODO : implement
return
"<unimplemented>"
;
m_x
=
m_y
=
0
;
auto
it
=
s
.
begin
();
auto
end
=
s
.
end
();
while
(
it
!=
end
)
result
+=
output_line
(
it
,
end
);
result
+=
"!"
;
return
result
;
}
std
::
string
RLEStructureWriter
::
state_to_str
(
unsigned
state
)
std
::
string
RLEStructureWriter
::
state_to_str
(
unsigned
state
)
const
{
if
(
state
==
0
)
return
"b"
;
...
...
@@ -62,3 +69,49 @@ std::string RLEStructureWriter::state_to_str(unsigned state)
return
std
::
string
(
1
,
page_char
)
+
std
::
string
(
1
,
offset_char
);
}
}
std
::
string
RLEStructureWriter
::
output_line
(
Structure
::
iterator
&
it
,
Structure
::
iterator
end
)
const
{
std
::
string
output
;
unsigned
line_difference
=
it
->
first
.
y
-
m_y
;
m_x
=
0
;
m_y
=
it
->
first
.
y
;
output
+=
rle
(
"$"
,
line_difference
);
while
(
it
!=
end
&&
it
->
first
.
y
==
(
int
)
m_y
)
output
+=
output_rle_state
(
it
,
end
);
return
output
;
}
std
::
string
RLEStructureWriter
::
output_rle_state
(
Structure
::
iterator
&
it
,
Structure
::
iterator
end
)
const
{
unsigned
zero_pad
=
it
->
first
.
x
-
m_x
;
unsigned
state
=
it
->
second
;
unsigned
len
=
1
;
while
(
std
::
next
(
it
)
!=
end
&&
std
::
next
(
it
)
->
second
==
state
&&
std
::
next
(
it
)
->
first
.
x
==
it
->
first
.
x
+
1
&&
std
::
next
(
it
)
->
first
.
y
==
it
->
first
.
y
)
{
std
::
advance
(
it
,
1
);
++
len
;
}
m_x
=
it
->
first
.
x
+
1
;
std
::
advance
(
it
,
1
);
// pad until first non-null state
return
rle
(
state_to_str
(
0
),
zero_pad
)
+
rle
(
state_to_str
(
state
),
len
);
}
std
::
string
RLEStructureWriter
::
rle
(
const
std
::
string
&
val
,
unsigned
count
)
const
{
if
(
count
==
0
)
return
""
;
else
if
(
count
==
1
)
return
val
;
else
return
std
::
to_string
(
count
)
+
val
;
}
tests/structure_test.cpp
View file @
feb51b5a
...
...
@@ -9,9 +9,10 @@
void
CellulutTests
::
test_structure
()
{
std
::
vector
<
std
::
pair
<
Coord
,
unsigned
>>
coords
;
std
::
vector
<
std
::
pair
<
Coord
,
unsigned
>>
normalized_coords
;
std
::
vector
<
std
::
pair
<
Coord
,
unsigned
>>
empty
;
coords
.
push_back
({{
1
,
3
},
3
});
coords
.
push_back
({{
-
1
,
2
},
1
});
coords
.
push_back
({{
1
,
3
},
3
});
normalized_coords
.
push_back
({{
2
,
1
},
3
});
coords
.
push_back
({{
-
1
,
2
},
1
});
normalized_coords
.
push_back
({{
0
,
0
},
1
});
{
Structure
s1
(
coords
.
begin
(),
coords
.
end
());
...
...
@@ -20,8 +21,8 @@ void CellulutTests::test_structure()
QCOMPARE
(
s1
.
size
(),
coords
.
size
());
QCOMPARE
(
s2
.
size
(),
coords
.
size
());
QVERIFY
(
std
::
is_permutation
(
coords
.
begin
(),
coords
.
end
(),
s1
.
begin
()));
QVERIFY
(
std
::
is_permutation
(
coords
.
begin
(),
coords
.
end
(),
s2
.
begin
()));
QVERIFY
(
std
::
is_permutation
(
normalized_
coords
.
begin
(),
normalized_
coords
.
end
(),
s1
.
begin
()));
QVERIFY
(
std
::
is_permutation
(
normalized_
coords
.
begin
(),
normalized_
coords
.
end
(),
s2
.
begin
()));
QCOMPARE
(
s1
.
width
(),
3
);
QCOMPARE
(
s1
.
height
(),
2
);
...
...
@@ -31,14 +32,13 @@ void CellulutTests::test_structure()
}
std
::
vector
<
std
::
pair
<
Coord
,
unsigned
>>
coords_with_zero
;
coords_with_zero
.
push_back
({{
1
,
3
},
3
});
coords_with_zero
.
push_back
({{
-
1
,
2
},
1
});
coords_with_zero
=
coords
;
coords_with_zero
.
push_back
({{
-
2
,
2
},
0
});
{
Structure
s1
(
coords_with_zero
.
begin
(),
coords_with_zero
.
end
());
QCOMPARE
(
s1
.
size
(),
2
);
// 2 cellules non nulles, on ignore les cellules à zéro qui sont toujours implicites
QVERIFY
(
std
::
is_permutation
(
coords
.
begin
(),
coords
.
end
(),
s1
.
begin
()));
QCOMPARE
(
s1
.
size
(),
coords
.
size
()
);
// 2 cellules non nulles, on ignore les cellules à zéro qui sont toujours implicites
QVERIFY
(
std
::
is_permutation
(
normalized_
coords
.
begin
(),
normalized_
coords
.
end
(),
s1
.
begin
()));
QCOMPARE
(
s1
.
width
(),
3
);
QCOMPARE
(
s1
.
height
(),
2
);
...
...
tests/structurereader_tests.cpp
View file @
feb51b5a
...
...
@@ -7,12 +7,12 @@
#include
"structure.hpp"
#include
"structurereader.hpp"
const
char
*
rle_glider
=
static
const
char
*
rle_glider
=
"#C This is a glider.
\n
"
"x = 3, y = 3
\n
"
"bo$2bo$3o!
\n
"
;
const
char
*
rle_glider_gun
=
static
const
char
*
rle_glider_gun
=
"#N Gosper glider gun
\n
"
"#C This was the first gun discovered.
\n
"
"#C As its name suggests, it was discovered by Bill Gosper.
\n
"
...
...
@@ -20,15 +20,15 @@ const char* rle_glider_gun =
"24bo$22bobo$12b2o6b2o12b2o$11bo3bo4b2o12b2o$2o8bo5bo3b2o$2o8bo3bob2o4b
\n
"
"obo$10bo5bo7bo$11bo3bo$12b2o!"
;
const
char
*
rle_wireworld
=
static
const
char
*
rle_wireworld
=
"x = 6, y = 7, rule = WireWorld
\n
"
".A$.C$4C$C2.3C$4C$.C$.A!"
;
const
char
*
json_test_1
=
static
const
char
*
json_test_1
=
"{
\n
"
"
\"
cells
\"
: [
\n
"
" {
\"
x
\"
:
1
,
\"
y
\"
:
2
,
\"
state
\"
: 1},
\n
"
" {
\"
x
\"
:
1
,
\"
y
\"
: 3,
\"
state
\"
: 3}
\n
"
" {
\"
x
\"
:
0
,
\"
y
\"
:
0
,
\"
state
\"
: 1},
\n
"
" {
\"
x
\"
:
2
,
\"
y
\"
: 3,
\"
state
\"
: 3}
\n
"
" ]
\n
"
"}"
;
...
...
@@ -97,8 +97,8 @@ void CellulutTests::test_json_structurereader()
try
{
Structure
stru
=
rle
.
read_structure
();
QCOMPARE
(
stru
.
size
(),
2
);
QVERIFY
(
std
::
count
(
stru
.
begin
(),
stru
.
end
(),
std
::
make_pair
<
Coord
,
unsigned
>
(
Coord
{
1
,
2
},
1
))
==
1
);
QVERIFY
(
std
::
count
(
stru
.
begin
(),
stru
.
end
(),
std
::
make_pair
<
Coord
,
unsigned
>
(
Coord
{
1
,
3
},
3
))
==
1
);
QVERIFY
(
std
::
count
(
stru
.
begin
(),
stru
.
end
(),
std
::
make_pair
<
Coord
,
unsigned
>
(
Coord
{
0
,
0
},
1
))
==
1
);
QVERIFY
(
std
::
count
(
stru
.
begin
(),
stru
.
end
(),
std
::
make_pair
<
Coord
,
unsigned
>
(
Coord
{
2
,
3
},
3
))
==
1
);
}
catch
(
const
std
::
exception
&
ex
)
{
...
...
tests/structurewriter_tests.cpp
View file @
feb51b5a
...
...
@@ -8,16 +8,60 @@
#include
"structurewriter.hpp"
#include
"structurereader.hpp"
static
const
char
*
rle_glider
=
"x = 3, y = 3
\n
"
"bo$2bo$3o!"
;
static
const
char
*
rle_glider_gun
=
"x = 36, y = 9
\n
"
"24bo$22bobo$12b2o6b2o12b2o$11bo3bo4b2o12b2o$2o8bo5bo3b2o$2o8bo3bob2o4b"
"obo$10bo5bo7bo$11bo3bo$12b2o!"
;
void
CellulutTests
::
test_rle_structurewriter
()
{
// TODO : écrire ces tests
try
{
Structure
stru
;
RLEStructureReader
reader
(
rle_glider
);
stru
=
reader
.
read_structure
();
RLEStructureWriter
writer
;
auto
out
=
writer
.
save_structure
(
stru
);
QCOMPARE
(
out
,
std
::
string
(
rle_glider
));
}
catch
(
const
std
::
exception
&
ex
)
{
fprintf
(
stderr
,
"Error is %s
\n
"
,
ex
.
what
());
QFAIL
(
"Exception thrown"
);
}
try
{
Structure
stru
;
RLEStructureReader
reader
(
rle_glider_gun
);
stru
=
reader
.
read_structure
();
RLEStructureWriter
writer
;
auto
out
=
writer
.
save_structure
(
stru
);
QCOMPARE
(
out
,
std
::
string
(
rle_glider_gun
));
}
catch
(
const
std
::
exception
&
ex
)
{
fprintf
(
stderr
,
"Error is %s
\n
"
,
ex
.
what
());
QFAIL
(
"Exception thrown"
);
}
}
void
CellulutTests
::
test_json_structurewriter
()
{
std
::
vector
<
std
::
pair
<
Coord
,
unsigned
>>
coords
;
coords
.
push_back
({{
1
,
2
},
3
});
coords
.
push_back
({{
-
1
,
2
},
1
});
coords
.
push_back
({{
0
,
0
},
3
});
coords
.
push_back
({{
1
,
2
},
1
});
coords
.
push_back
({{
5
,
8
},
5
});
try
{
...
...
Write
Preview
Supports
Markdown
0%
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!
Cancel
Please
register
or
sign in
to comment