Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
D
dsprog
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
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
Manuel Bucher
dsprog
Commits
621400cb
Commit
621400cb
authored
6 years ago
by
Manuel Bucher
Browse files
Options
Downloads
Patches
Plain Diff
Refractored Array und List
parent
97a3c65f
Branches
Branches containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
Makefile
+1
-1
1 addition, 1 deletion
Makefile
loesung.c
+146
-139
146 additions, 139 deletions
loesung.c
with
147 additions
and
140 deletions
Makefile
+
1
−
1
View file @
621400cb
...
...
@@ -3,7 +3,7 @@ all: loesung
WARNINGS
=
-Wall
#-Werror
OPTIONAL
=
-Wextra
-Wpedantic
-Wshadow
DEBUG
=
-g
-ggdb
-fno-omit-frame-pointer
OPTIMIZE
=
-O
2
-std
=
c11
OPTIMIZE
=
-O
g
-std
=
c11
loesung
:
Makefile loesung.c
$(
CC
)
-o
$@
$(
WARNINGS
)
$(
OPTIONAL
)
$(
DEBUG
)
$(
OPTIMIZE
)
loesung.c
...
...
This diff is collapsed.
Click to expand it.
loesung.c
+
146
−
139
View file @
621400cb
...
...
@@ -7,13 +7,30 @@
typedef
struct
Tile
{
uint32_t
x
;
uint32_t
y
;
struct
Tile
*
p_n
;
// north, used for initial list
struct
Tile
*
p_next
;
// used for list
struct
Tile
*
p_n
;
// north
struct
Tile
*
p_e
;
// east
struct
Tile
*
p_s
;
// south
struct
Tile
*
p_w
;
// west
}
Tile
;
// Reservieren und initialisieren des Speicherplatz eines Tiles
Tile
*
tile_new
()
{
Tile
*
p_tile
=
malloc
(
sizeof
(
Tile
));
if
(
p_tile
==
NULL
)
{
// failed to allocate memory
return
NULL
;
}
p_tile
->
x
=
0
;
p_tile
->
y
=
0
;
p_tile
->
p_next
=
NULL
;
p_tile
->
p_n
=
NULL
;
p_tile
->
p_e
=
NULL
;
p_tile
->
p_s
=
NULL
;
p_tile
->
p_w
=
NULL
;
return
p_tile
;
}
int
tile_compare
(
const
void
*
p
,
const
void
*
q
)
{
const
Tile
*
s
=
*
(
const
Tile
**
)
p
;
const
Tile
*
t
=
*
(
const
Tile
**
)
q
;
...
...
@@ -35,62 +52,73 @@ int tile_compare(const void *p, const void *q) {
/** List von Tiles */
typedef
struct
List
{
Tile
*
p_top
;
uint32_t
size
;
uint32_t
num_tiles
;
uint32_t
num_odd
;
// #ungerade Felder (`x - y` ist ungerade)
Tile
max
;
Tile
min
;
}
List
;
/** Initialisieren einer leeren Liste */
void
list_init
(
List
*
s
)
{
s
->
p_top
=
NULL
;
s
->
size
=
0
;
void
list_init
(
List
*
this
)
{
this
->
p_top
=
NULL
;
this
->
num_tiles
=
0
;
this
->
num_odd
=
0
;
this
->
min
.
x
=
UINT32_MAX
;
this
->
min
.
y
=
UINT32_MAX
;
this
->
max
.
x
=
0
;
this
->
max
.
y
=
0
;
}
/** Hinzufuegen eines leeren Elementes zur Liste
/** Min-Max funktionen fuer uint32_t */
inline
uint32_t
min
(
uint32_t
a
,
uint32_t
b
)
{
return
a
<
b
?
a
:
b
;
}
inline
uint32_t
max
(
uint32_t
a
,
uint32_t
b
)
{
return
a
>
b
?
a
:
b
;
}
/** Hinzufuegen von einem Tile zur Liste
*
* Voraussetzung: Die Liste muss initialisiert sein.
* Rueckgabe: Hinzugefuegtes, initialisiertes Tile
*/
Tile
*
list_push
(
List
*
s
)
{
Tile
*
p_tile
=
malloc
(
sizeof
(
Tile
));
if
(
p_tile
==
NULL
)
{
// failed to allocate memory
return
NULL
;
}
p_tile
->
x
=
0
;
p_tile
->
y
=
0
;
p_tile
->
p_n
=
s
->
p_top
;
p_tile
->
p_e
=
NULL
;
p_tile
->
p_s
=
NULL
;
p_tile
->
p_w
=
NULL
;
s
->
p_top
=
p_tile
;
s
->
size
++
;
return
p_tile
;
}
/** Entfernen des obersten Elementes von der Liste und zurueckgeben des Tiles
*
* Der List muss mindestens ein Element besitzen
*/
Tile
*
list_pop
(
List
*
s
)
{
Tile
*
p_tile
=
s
->
p_top
;
s
->
p_top
=
s
->
p_top
->
p_n
;
s
->
size
--
;
return
p_tile
;
void
list_push
(
List
*
this
,
Tile
*
p_tile
)
{
p_tile
->
p_next
=
this
->
p_top
;
this
->
p_top
=
p_tile
;
// Reichweite der Liste ermitteln
this
->
min
.
x
=
min
(
this
->
min
.
x
,
p_tile
->
x
);
this
->
min
.
y
=
min
(
this
->
min
.
y
,
p_tile
->
y
);
this
->
max
.
x
=
max
(
this
->
max
.
x
,
p_tile
->
x
);
this
->
max
.
y
=
max
(
this
->
max
.
x
,
p_tile
->
y
);
this
->
num_tiles
++
;
this
->
num_odd
+=
(
p_tile
->
x
-
p_tile
->
y
)
&
1
;
}
/** Freigeben des reservierten Speichers von der Liste
*
* Alle Tiles
weReaden
mit free vom
s
peicher
deallocaiert
* Alle Tiles mit free vom
S
peicher
freigeben
*/
void
list_free
(
List
*
s
)
{
Tile
*
p_cur
=
s
->
p_top
;
s
->
p_top
=
NULL
;
void
list_free
(
List
*
thi
s
)
{
Tile
*
p_cur
=
thi
s
->
p_top
;
thi
s
->
p_top
=
NULL
;
while
(
p_cur
!=
NULL
)
{
Tile
*
p_next
=
p_cur
->
p_n
;
Tile
*
p_next
=
p_cur
->
p_n
ext
;
free
(
p_cur
);
p_cur
=
p_next
;
}
}
/** pruefen, ob genausoviele gerade und ungerade Kacheln existieren,
* ohne einen Overflow zu erzeugen
* notwendiges Kriterium fuer unzusammenhaengender graph und hinreichendes
* fuer zusammenhaengender
*/
bool
list_possible
(
List
*
this
)
{
return
this
->
num_tiles
-
this
->
num_odd
==
this
->
num_odd
;
}
/** Zurueckgeben, ob graph ein vollstaendiges Rechteck ist */
bool
list_rectangle
(
List
*
this
)
{
return
(
this
->
max
.
x
-
this
->
min
.
x
)
*
(
this
->
max
.
y
-
this
->
min
.
y
)
==
this
->
num_tiles
;
// TODO: check for overflow?
}
typedef
enum
ReadResult
{
ReadOk
,
ReadEof
,
...
...
@@ -100,16 +128,6 @@ typedef enum ReadResult {
ReadErrTooManyNumbers
,
ReadErrOutOfMemory
,
}
ReadResult
;
typedef
struct
Field
{
Tile
t_min
;
Tile
t_max
;
List
tile_list
;
Tile
*
(
*
tile_array
);
uint32_t
num_tiles
;
}
Field
;
// TODO: entfernen dieses Structs und nutzen von kleineren Strukturen:
// list + tile_array
/** Parsen einer Kachel(Tile) aus einer Zeile von StdIn
*
* Die Zahlen weReaden in das uebergebene Struct pTile geschrieben, sind aber
...
...
@@ -135,16 +153,14 @@ ReadResult read_line(Tile* p_tile){
cur_whitespace
=
false
;
cur_number
++
;
}
// 429496730 = 2^32 / 10, daher wenn `p_cur` groesser ist, wi
Rea
d ein
// 429496730 = 2^32 / 10, daher wenn `p_cur` groesser ist, wi
r
d ein
// overflow erzeugt
if
(
*
p_cur
>
429496729
)
{
printf
(
"Multiplizieren ueberlauf %u
\n
"
,
*
p_cur
);
return
ReadErrIntegerOverflow
;
}
(
*
p_cur
)
*=
10
;
int
digit
=
c
-
'0'
;
if
(
*
p_cur
>
UINT32_MAX
-
digit
)
{
printf
(
"Addieren ueberlauf %u
\n
"
,
*
p_cur
);
return
ReadErrIntegerOverflow
;
}
(
*
p_cur
)
+=
digit
;
...
...
@@ -166,48 +182,15 @@ ReadResult read_line(Tile* p_tile){
return
ReadOk
;
}
/** Min-Max funktionen fuer uint32_t */
inline
uint32_t
min
(
uint32_t
a
,
uint32_t
b
)
{
return
a
<
b
?
a
:
b
;
}
inline
uint32_t
max
(
uint32_t
a
,
uint32_t
b
)
{
return
a
>
b
?
a
:
b
;
}
/** Initialisieren der Variablen im Feld
*
* Voraussetzung: Speicher vom Feld muss allocated sein.
*/
void
field_init
(
Field
*
f
)
{
f
->
t_min
.
x
=
UINT32_MAX
;
f
->
t_min
.
y
=
UINT32_MAX
;
f
->
t_max
.
x
=
0
;
f
->
t_max
.
y
=
0
;
// initialisieren der Liste
list_init
(
&
f
->
tile_list
);
f
->
tile_array
=
0
;
f
->
num_tiles
=
0
;
}
/** Freigeben des im Heap reservierten speichers des fields f */
void
field_drop
(
Field
*
f
)
{
uint32_t
num_tiles
=
f
->
tile_list
.
size
;
if
(
f
->
tile_array
!=
NULL
)
{
for
(
uint32_t
i
=
0
;
i
<
num_tiles
;
i
++
)
{
free
(
f
->
tile_array
[
i
]);
}
free
(
f
->
tile_array
);
}
else
{
list_free
(
&
f
->
tile_list
);
}
}
/** Liest das Input von StdIn und schreibt das Ergebnis in das uebergebene Feld
/** Liest das Input von StdIn und schreibt das Ergebnis in die uebergebene Liste
*
* Laufzeit: O(n)
* Speicherbedarf: O(n)
*
* Parameter:
* - Field* f pointer auf ein uninitialisiertes Feld, nach dem ausfuehren der
* Funktion ist das Feld initialisiert, wenn es sich um eine gueltige Eingabe
* handelt. `f->tile_list->size` Ist im Fehlerfall die Zeile, in dem die Eingabe
* ungueltig ist.
* - List* f ist ein Pointer auf eine initialisierte List, wird mit Eingabe
* gefuellt, im Fehlerfall ist die groesse `num_tiles` die Zeile, in welche
* der Fehler aufgetreten ist
*
* Return:
* - ReadResult:
...
...
@@ -215,24 +198,21 @@ void field_drop(Field *f) {
* ReadErr..., falls die Eingabe ungueltig ist. `f` ist dann nicht vollstaendig
* initialisiert
*/
ReadResult
field_init_tile_list
(
Field
*
f
)
{
ReadResult
parse_input
(
List
*
this
)
{
while
(
1
)
{
Tile
*
t
=
list_push
(
&
f
->
tile_
list
);
// neues Element
in die Liste einfueg
en
if
(
t
==
NULL
)
{
Tile
*
p_tile
=
tile_
new
(
);
// neues Element
erstell
en
if
(
p_tile
==
NULL
)
{
return
ReadErrOutOfMemory
;
}
ReadResult
result
=
read_line
(
t
);
ReadResult
result
=
read_line
(
p_tile
);
switch
(
result
)
{
case
ReadOk
:
// Reichweite des Feldes ermitteln
f
->
t_min
.
x
=
min
(
f
->
t_min
.
x
,
t
->
x
);
f
->
t_min
.
y
=
min
(
f
->
t_min
.
y
,
t
->
y
);
f
->
t_max
.
x
=
max
(
f
->
t_max
.
x
,
t
->
x
);
f
->
t_max
.
y
=
max
(
f
->
t_max
.
x
,
t
->
y
);
// einfuegen in die Liste
list_push
(
this
,
p_tile
);
break
;
case
ReadEof
:
list_pop
(
&
f
->
tile_list
);
if
(
f
->
tile_list
.
size
==
1
)
{
free
(
p_tile
);
if
(
this
->
num_tiles
==
0
)
{
return
ReadEof
;
}
else
{
return
ReadOk
;
...
...
@@ -243,6 +223,24 @@ ReadResult field_init_tile_list(Field *f) {
}
}
/** Array in heap for accessing tiles in O(1)
*/
typedef
struct
Array
{
uint32_t
num_tiles
;
Tile
*
(
*
tiles
);
}
Array
;
/** Freigeben des im Heap reservierten Speichers des tile_arrays f
* inklusive der Tiles */
void
array_drop
(
Array
*
this
)
{
if
(
this
->
tiles
!=
NULL
)
{
for
(
uint32_t
i
=
0
;
i
<
this
->
num_tiles
;
i
++
)
{
free
(
this
->
tiles
[
i
]);
}
free
(
this
->
tiles
);
}
}
typedef
enum
MallocResult
{
MallocFailed
,
MallocOk
,
...
...
@@ -251,18 +249,17 @@ typedef enum MallocResult {
*
* Laufzeit: O(n)
*/
MallocResult
field_init_tile_array
(
Field
*
f
)
{
f
->
tile
_array
=
malloc
(
f
->
tile_list
.
size
*
sizeof
(
Tile
*
));
if
(
f
->
tile
_array
==
NULL
)
{
MallocResult
array_from_list
(
Array
*
this
,
List
*
p_list
)
{
this
->
tile
s
=
malloc
(
p_list
->
num_tiles
*
sizeof
(
Tile
*
));
if
(
this
->
tile
s
==
NULL
)
{
return
MallocFailed
;
}
Tile
*
cur
=
f
->
tile_list
.
p_top
;
f
->
num_tiles
=
f
->
tile_list
.
size
;
for
(
uint32_t
i
=
0
;
i
<
f
->
tile_list
.
size
;
i
++
)
{
f
->
tile_array
[
i
]
=
cur
;
cur
=
cur
->
p_n
;
f
->
tile_array
[
i
]
->
p_n
=
NULL
;
this
->
num_tiles
=
p_list
->
num_tiles
;
Tile
*
cur
=
p_list
->
p_top
;
for
(
uint32_t
i
=
0
;
i
<
this
->
num_tiles
;
i
++
)
{
this
->
tiles
[
i
]
=
cur
;
cur
=
cur
->
p_next
;
this
->
tiles
[
i
]
->
p_next
=
NULL
;
}
return
MallocOk
;
}
...
...
@@ -273,12 +270,12 @@ MallocResult field_init_tile_array(Field *f) {
* Rueckgabe: 0 falls alles ok
* 1 falls Dopplungen vorkommen TODO: enum
*/
int
field
_find_neighbours
(
Field
*
f
)
{
int
array
_find_neighbours
(
Array
*
this
)
{
uint32_t
i
=
0
;
// vergleich mit oberer Zeile
uint32_t
begin_line
=
0
;
for
(
uint32_t
j
=
1
;
j
<
f
->
num_tiles
;
j
++
)
{
Tile
*
p_cur
=
f
->
tile
_array
[
j
];
Tile
*
p_east
=
f
->
tile
_array
[
j
-
1
];
for
(
uint32_t
j
=
1
;
j
<
this
->
num_tiles
;
j
++
)
{
Tile
*
p_cur
=
this
->
tile
s
[
j
];
Tile
*
p_east
=
this
->
tile
s
[
j
-
1
];
// ermitteln der ost/west-Beziehung
if
(
p_cur
->
y
==
p_east
->
y
)
{
if
(
p_cur
->
x
==
p_east
->
x
)
{
...
...
@@ -292,14 +289,14 @@ int field_find_neighbours(Field *f) {
begin_line
=
i
;
}
// ermitteln der nord/sued-Beziehung
Tile
*
p_north
=
f
->
tile
_array
[
i
];
Tile
*
p_north
=
this
->
tile
s
[
i
];
if
(
p_north
->
y
<
p_cur
->
y
-
1
)
{
i
=
begin_line
;
// Luecke zwischen zeilen
}
else
if
(
p_north
->
y
==
p_cur
->
y
-
1
)
{
// finden, ob paar existiert, zurzeit O(n).
// TODO: lohnt sich binaere suche mit O(log n)?
for
(;
f
->
tile
_array
[
i
]
->
y
<
p_cur
->
y
&&
i
<
begin_line
;
i
++
);
p_north
=
f
->
tile
_array
[
i
];
for
(;
this
->
tile
s
[
i
]
->
y
<
p_cur
->
y
&&
i
<
begin_line
;
i
++
);
p_north
=
this
->
tile
s
[
i
];
if
(
p_north
->
x
==
p_cur
->
x
)
{
p_north
->
p_s
=
p_cur
;
p_cur
->
p_n
=
p_north
;
...
...
@@ -309,19 +306,19 @@ int field_find_neighbours(Field *f) {
return
0
;
}
void
field
_print
(
Field
*
f
)
{
void
array
_print
(
Array
*
this
)
{
printf
(
"# Array
\n
"
);
for
(
uint32_t
i
=
0
;
i
<
f
->
tile_list
.
size
;
i
++
)
{
printf
(
"%
d
%
d
\n
"
,
f
->
tile
_array
[
i
]
->
x
,
f
->
tile
_array
[
i
]
->
y
);
for
(
uint32_t
i
=
0
;
i
<
this
->
num_tiles
;
i
++
)
{
printf
(
"%
u
%
u
\n
"
,
this
->
tile
s
[
i
]
->
x
,
this
->
tile
s
[
i
]
->
y
);
}
}
int
main
(
void
)
{
// erstellen des
main Objekt
Field
field
;
field
_init
(
&
field
);
// initialiseren der Variab
le
n
ReadResult
result
=
field_init_
tile_list
(
&
field
);
// lesen des Inputs
// erstellen des
Liste zum parsen des inputs
List
tile_list
;
list
_init
(
&
tile_list
);
// Liste ist owner von Ti
le
s
ReadResult
result
=
parse_input
(
&
tile_list
);
// lesen des Inputs
switch
(
result
)
{
case
ReadOk
:
break
;
...
...
@@ -329,44 +326,54 @@ int main (void)
// bei leerer Eingabe nichts ausgeben
return
EXIT_SUCCESS
;
case
ReadErrIntegerOverflow
:
fprintf
(
stderr
,
"Error in line %d: too big integer
\n
"
,
field
.
tile_list
.
size
);
field_drop
(
&
field
);
fprintf
(
stderr
,
"Error in line %d: too big integer
\n
"
,
tile_list
.
num_tiles
);
list_free
(
&
tile_list
);
return
EXIT_FAILURE
;
case
ReadErrNonDigitCharacter
:
fprintf
(
stderr
,
"Error in line %d: invalid character
\n
"
,
field
.
tile_list
.
size
);
field_drop
(
&
field
);
fprintf
(
stderr
,
"Error in line %d: invalid character
\n
"
,
tile_list
.
num_tiles
);
list_free
(
&
tile_list
);
return
EXIT_FAILURE
;
case
ReadErrTooFewNumbers
:
fprintf
(
stderr
,
"Error in line %d: Too few numbers, expected exactly 2
\n
"
,
field
.
tile_list
.
size
);
field_drop
(
&
field
);
tile_list
.
num_tiles
);
list_free
(
&
tile_list
);
return
EXIT_FAILURE
;
case
ReadErrTooManyNumbers
:
fprintf
(
stderr
,
"Error in line %d: Too much numbers, expected exactly 2
\n
"
,
field
.
tile_list
.
size
);
field_drop
(
&
field
);
tile_list
.
num_tiles
);
list_free
(
&
tile_list
);
return
EXIT_FAILURE
;
case
ReadErrOutOfMemory
:
fprintf
(
stderr
,
"Error in line %d: Failed to allocate more memory"
,
field
.
tile_list
.
size
);
tile_list
.
num_tiles
);
list_free
(
&
tile_list
);
return
EXIT_FAILURE
;
}
// turn the list into an array
if
(
field_init_tile_array
(
&
field
)
==
MallocFailed
)
{
Array
tile_array
;
// uebertragen der Liste in ein Array, und uebergeben des ownership der Tiles
// an das Array
if
(
array_from_list
(
&
tile_array
,
&
tile_list
)
==
MallocFailed
)
{
fprintf
(
stderr
,
"Error: Failed to allocate enough memory"
);
list_free
(
&
tile_list
);
// fehlgeschlagen, noch ist liste owner.
return
EXIT_FAILURE
;
}
qsort
(
field
.
tile_array
,
field
.
tile_list
.
size
,
sizeof
(
Tile
*
),
tile_compare
);
if
(
field_find_neighbours
(
&
field
))
{
// TODO: pruefen, ob notwendiges Kriterium erfuellt,
// TODO: Falls Rechteck, dieses Ausgeben.
//array_print(&tile_array);
qsort
(
tile_array
.
tiles
,
tile_array
.
num_tiles
,
sizeof
(
Tile
*
),
tile_compare
);
if
(
array_find_neighbours
(
&
tile_array
))
{
fprintf
(
stderr
,
"Error: Duplicated entry
\n
"
);
array_drop
(
&
tile_array
);
return
EXIT_FAILURE
;
}
//field_print(&field);
// TODO: Untertilesets finden
// TODO: Pro
blem fuer die Untertilesets loesen
// TODO: Loesung ausgeben
// TODO: Pro
Untertileset schauen ob notwendiges kriterium
// TODO: Loesung ausgeben
(schwerer Teil)
field
_drop
(
&
field
);
array
_drop
(
&
tile_array
);
return
EXIT_SUCCESS
;
}
This diff is collapsed.
Click to expand it.
Preview
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!
Save comment
Cancel
Please
register
or
sign in
to comment