Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
P
Python prototype
Manage
Activity
Members
Labels
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Model registry
Analyze
Value stream analytics
Contributor 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
Cinematinator
Python prototype
Commits
ac22c1cb
Verified
Commit
ac22c1cb
authored
4 years ago
by
Maarten van den Berg
Browse files
Options
Downloads
Patches
Plain Diff
Add simple greedy online solver
parent
d4759bcc
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
cinematinator/cli.py
+32
-1
32 additions, 1 deletion
cinematinator/cli.py
cinematinator/online_test.py
+53
-0
53 additions, 0 deletions
cinematinator/online_test.py
cinematinator/types.py
+30
-0
30 additions, 0 deletions
cinematinator/types.py
with
115 additions
and
1 deletion
cinematinator/cli.py
+
32
−
1
View file @
ac22c1cb
...
...
@@ -10,6 +10,7 @@ from cinematinator.instance_io import (
parse_group_counts
,
prettyprint_cinema
,
)
from
cinematinator.online_test
import
TestOnlineSolver
from
cinematinator.offline
import
BruteforceOfflineSolver
from
cinematinator.mip_test
import
MIPSolver
from
cinematinator.simple_cinema
import
SimpleCinema
...
...
@@ -44,7 +45,7 @@ class OfflineSolvers(enum.Enum):
@click.option
(
"
--solver
"
,
"
solver_name
"
,
type
=
click
.
Choice
(
OfflineSolvers
.
_member_names_
),
type
=
click
.
Choice
(
OfflineSolvers
.
_member_names_
),
# type:ignore
default
=
"
mip
"
,
)
@click.argument
(
"
input_file
"
,
type
=
click
.
File
(
mode
=
"
r
"
))
...
...
@@ -82,5 +83,35 @@ def edge_algo_cmd(input_file: TextIO) -> None:
print
(
result
)
@cli.command
(
"
online
"
)
@click.argument
(
"
input_file
"
,
type
=
click
.
File
(
mode
=
"
r
"
))
def
online_cmd
(
input_file
:
TextIO
)
->
None
:
"""
Online dingos
"""
cinema
=
parse_cinema
(
input_file
)
solver
=
TestOnlineSolver
(
cinema
)
for
line
in
input_file
:
input
=
line
.
strip
()
group_size
=
int
(
input
)
if
group_size
==
0
:
print
(
solver
.
cinema
.
get_amount_people_seated
())
else
:
maybe_location
=
solver
.
try_seat_group
(
group_size
)
if
maybe_location
is
None
:
print
(
"
0 0
"
)
else
:
x
,
y
=
maybe_location
print
(
f
"
{
x
+
1
}
{
y
+
1
}
"
)
if
__name__
==
"
__main__
"
:
cli
()
This diff is collapsed.
Click to expand it.
cinematinator/online_test.py
0 → 100644
+
53
−
0
View file @
ac22c1cb
from
__future__
import
annotations
from
typing
import
Optional
,
Tuple
,
List
from
cinematinator.types
import
Cinema
,
Coordinates
class
TestOnlineSolver
:
def
__init__
(
self
,
cinema
:
Cinema
)
->
None
:
self
.
cinema
=
cinema
def
try_seat_group
(
self
,
group_size
:
int
)
->
Optional
[
Coordinates
]:
potential_locations
:
List
[
Tuple
[
int
,
Coordinates
]]
=
[]
for
y
in
range
(
self
.
cinema
.
height
):
potential_locations
.
extend
(
scan_row
(
self
.
cinema
,
group_size
,
y
))
potential_locations
.
sort
()
if
len
(
potential_locations
)
==
0
:
return
None
penalty
,
optimal_location
=
potential_locations
[
0
]
seat_at_x
,
seat_at_y
=
optimal_location
self
.
cinema
.
seat_group
(
seat_at_x
,
seat_at_y
,
group_size
)
return
optimal_location
def
scan_row
(
cinema
:
Cinema
,
group_size
:
int
,
y
:
int
)
->
List
[
Tuple
[
int
,
Coordinates
]]:
"""
Scan the row at the given height for open spots that fit the given group size, then
return the starting location that fits the group while blocking the smallest amount
of still-available seats.
If there are multiple eligible locations that block the same number of
still-available seats, return the leftmost position.
If there is such a spot, return a 2-tuple (blocked_seats, x).
If there is no such spot, return None.
"""
potential_locations
:
List
[
Tuple
[
int
,
Coordinates
]]
=
[]
# Optimalization: we will never be able to seat a group at a position less than
# group_size from the right edge.
for
x
in
range
(
0
,
cinema
.
width
-
group_size
+
1
):
if
cinema
.
can_seat_group
(
x
,
y
,
group_size
):
penalty
=
cinema
.
newly_blocked_seats
(
x
,
y
,
group_size
)
potential_locations
.
append
((
penalty
,
(
x
,
y
)))
return
potential_locations
This diff is collapsed.
Click to expand it.
cinematinator/types.py
+
30
−
0
View file @
ac22c1cb
...
...
@@ -151,6 +151,36 @@ class Cinema:
return
amount
def
newly_blocked_seats
(
self
,
x
:
int
,
y
:
int
,
group_size
:
int
)
->
int
:
"""
Return the amount of currently available seats that would become blocked if a
group were to be seated at this location.
"""
result
:
int
=
0
for
check_y
in
(
y
-
1
,
y
+
1
):
if
check_y
not
in
range
(
0
,
self
.
height
):
continue
start_x
=
max
(
x
-
1
,
0
)
end_x
=
min
(
x
+
1
,
self
.
width
)
+
1
for
check_x
in
range
(
start_x
,
end_x
+
1
):
if
self
[
check_x
,
check_y
]
==
SeatStatus
.
Available
:
result
+=
1
for
check_x
in
(
x
-
2
,
x
-
1
,
x
+
group_size
+
1
,
x
+
group_size
+
2
):
if
check_x
not
in
range
(
0
,
self
.
width
):
continue
if
self
[
check_x
,
y
]
==
SeatStatus
.
Available
:
result
+=
1
return
result
class
OfflineSolverProtocol
(
Protocol
):
"""
...
...
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