Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
G
Google code jam solutions
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
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
Julien Courtiel
Google code jam solutions
Commits
ad1d5af0
Commit
ad1d5af0
authored
2 years ago
by
Julien Courtiel
Browse files
Options
Downloads
Patches
Plain Diff
solution of Ex1 - 2021
parent
06d228c5
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
2021/Qualification Round/Exercice 1 - Reversort.py
+234
-0
234 additions, 0 deletions
2021/Qualification Round/Exercice 1 - Reversort.py
README.md
+5
-2
5 additions, 2 deletions
README.md
with
239 additions
and
2 deletions
2021/Qualification Round/Exercice 1 - Reversort.py
0 → 100644
+
234
−
0
View file @
ad1d5af0
### Pour les tests (à ne pas copier) ###
entree
=
"""
3
71
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 71 69 67 65 63 61 59 57 55 53 51 49 47 45 43 41 39 37 35 33 31 29 27 25 23 21 19 17 15 13 11 9 7 5 3 1
3
2 3 1
18
10 3 6 8 7 1 5 4 2 9 11 12 14 13 15 16 17 18
"""
import
sys
from
io
import
StringIO
sys
.
stdin
=
StringIO
(
entree
)
### Définition d'une solution naïve ###
def
cout_quadratique
(
tab
):
"""
Renvoie le coût de Reversort : autrement dit la somme des longueurs des bouts du tableau qui sont inversés.
Ceci implémante la solution attendue par le concours.
La complexité est quadratique.
"""
cout
=
0
n
=
len
(
tab
)
for
i
in
range
(
n
-
1
):
j
=
min
(
range
(
i
,
n
)
,
key
=
lambda
x
:
tab
[
x
]
)
cout
+=
j
-
i
+
1
#On procède à l'inversion de la sous-liste :
for
k
in
range
(
0
,(
j
-
i
)
//
2
+
1
):
tab
[
i
+
k
],
tab
[
j
-
k
]
=
tab
[
j
-
k
],
tab
[
i
+
k
]
return
cout
### Tentative d'une solution plus rapide ###
class
ABR
:
"""
Cette première classe décrit des simples ABR qui déterminent dans quel intervalle les positions
successives de 2, 3, ... apparentiennent.
Une fois qu
'
on aura trouvé cet invervalle, on appliquera à la position de l
'
entier une succession
de transformations affines (cf classe suivante)
"""
def
__init__
(
self
,
x
):
"""
Initialise un noeud de l
'
ABR à x
"""
self
.
valeur
=
x
self
.
gauche
=
None
self
.
droit
=
None
def
__repr__
(
self
):
if
self
.
gauche
==
None
and
self
.
droit
==
None
:
return
repr
(
self
.
valeur
)
retour
=
'
\n
'
return
f
"
|
{
repr
(
self
.
gauche
).
replace
(
retour
,
retour
+
'
|
'
)
}
\n
{
self
.
valeur
}
\n
|
{
repr
(
self
.
droit
).
replace
(
retour
,
retour
+
'
|
'
)
}
"
class
arbre_affine
:
"""
Cette classe décrit des arbres orientés des feuilles vers la racine.
Les feuilles correspondent à des intervalles dans lesquels la prochaine position peut appartenir.
On va remonter dans l
'
arbre et appliquer des transformations affines successives pour au final
obtenir la position de l
'
élément après renversements des sous-listes.
"""
def
__init__
(
self
):
"""
Initialise un noeud de l
'
ABR à x
"""
self
.
parent
=
None
# Coefficients de la transformation x -> a*x + b
self
.
coeff
=
(
1
,
0
)
self
.
est_fils_gauche
=
True
def
__repr__
(
self
):
if
self
.
parent
==
None
:
return
"
racine
"
conn
=
'
-
'
if
self
.
est_fils_gauche
else
'
~
'
return
f
"
[
{
id
(
self
)
%
100
//
4
}
]
{
self
.
coeff
}
{
conn
}
>
{
repr
(
self
.
parent
)
}
"
def
composition
(
X
,
Xp
):
a
,
b
=
X
ap
,
bp
=
Xp
return
(
a
*
ap
,
ap
*
b
+
bp
)
def
cout_via_ABR
(
tab
):
"""
Renvoie le coût de Reversort : autrement dit la somme des longueurs des bouts du tableau qui sont inversés.
La complexité est en O(N log(N))
"""
n
=
len
(
tab
)
#pos va contenir les positions de chaque élément dans le tableau
pos
=
[
-
1
]
*
(
n
+
1
)
for
i
,
x
in
enumerate
(
tab
):
pos
[
x
]
=
i
# Au départ
A
=
ABR
(
pos
[
1
])
A
.
gauche
=
ABR
(
arbre_affine
())
A
.
droit
=
ABR
(
arbre_affine
())
racine
=
arbre_affine
()
A
.
gauche
.
valeur
.
parent
=
racine
A
.
gauche
.
valeur
.
coeff
=
(
-
1
,
pos
[
1
])
A
.
droit
.
valeur
.
parent
=
racine
A
.
droit
.
valeur
.
est_fils_gauche
=
False
cout
=
pos
[
1
]
+
1
#Traitement des nombres 1 par 1
for
x
in
range
(
2
,
n
):
#On commence par trouver l'intervalle dans lequel pos[i] appartient
p
=
pos
[
x
]
tmp
=
A
while
(
not
(
tmp
.
gauche
==
None
and
tmp
.
droit
==
None
)
):
if
p
<
tmp
.
valeur
:
tmp
=
tmp
.
gauche
else
:
tmp
=
tmp
.
droit
G
=
tmp
.
valeur
#On rajoute un nouveau noeud à l'ABR
tmp
.
valeur
=
p
tmp
.
gauche
=
ABR
(
G
)
D
=
arbre_affine
()
tmp
.
droit
=
ABR
(
D
)
#On remonte à la racine de l'arbre affine
tmp
=
G
coeffg
=
(
1
,
0
)
coeffd
=
(
1
,
0
)
while
(
tmp
.
parent
!=
None
)
:
tc
=
tmp
.
coeff
if
tc
[
0
]
==
-
1
:
G
,
D
=
D
,
G
coeffg
,
coeffd
=
coeffd
,
coeffg
p
=
tc
[
0
]
*
p
+
tc
[
1
]
coeffg
=
composition
(
coeffg
,
tc
)
coeffd
=
composition
(
coeffd
,
tc
)
if
tmp
.
est_fils_gauche
:
D
.
est_fils_gauche
=
True
D
.
parent
=
tmp
.
parent
D
.
coeff
=
coeffd
coeffd
=
(
1
,
0
)
D
=
tmp
.
parent
else
:
G
.
est_fils_gauche
=
False
G
.
parent
=
tmp
.
parent
G
.
coeff
=
coeffg
coeffg
=
(
1
,
0
)
G
=
tmp
.
parent
tmp
=
tmp
.
parent
#Normalement, si j'ai fait mon taf, G doit contenir des valeurs <p, et D > p
cout
+=
p
-
x
+
2
G
.
est_fils_gauche
=
True
D
.
est_fils_gauche
=
False
racine
=
arbre_affine
()
G
.
parent
=
racine
D
.
parent
=
racine
G
.
coeff
=
composition
(
coeffg
,
(
-
1
,
p
+
x
-
1
)
)
D
.
coeff
=
coeffd
return
cout
### BENCHMARK ###
import
time
import
matplotlib.pyplot
as
plt
def
liste_aleatoire
(
longueur
):
import
random
L
=
[
i
for
i
in
range
(
1
,
longueur
+
1
)]
random
.
shuffle
(
L
)
return
L
def
test
(
liste_fonctions
,
n
):
temps_execution
=
[]
for
fct
in
liste_fonctions
:
#entree à changer ci-dessous :
entree
=
liste_aleatoire
(
n
)
t
=
time
.
time
()
fct
(
entree
)
temps_execution
.
append
(
time
.
time
()
-
t
)
return
temps_execution
def
trace_courbes
(
liste_fonctions
,
debut
,
fin
):
X
=
[]
Y
=
[
[]
for
j
in
range
(
len
(
liste_fonctions
))
]
for
i
in
range
(
debut
,
fin
,
max
((
fin
-
debut
)
//
100
,
1
)):
plt
.
clf
()
X
.
append
(
i
)
TE
=
test
(
liste_fonctions
,
i
)
for
j
in
range
(
len
(
TE
)):
Y
[
j
].
append
(
TE
[
j
])
plt
.
plot
(
X
,
Y
[
j
])
plt
.
draw
()
plt
.
pause
(
0.001
)
### Traitement du problème ###
T
=
int
(
input
())
for
k
in
range
(
T
):
n
=
int
(
input
())
tableau
=
list
(
map
(
int
,
input
().
split
(
"
"
)))
print
(
f
"
Case #
{
k
+
1
}
:
{
cout_via_ABR
(
tableau
)
}
"
)
This diff is collapsed.
Click to expand it.
README.md
+
5
−
2
View file @
ad1d5af0
# Google code jam solutions
En français
:)
My code is commented in French, sorry for that
:)
Voici pour l'instant ce qui a été réalisé
:
Here what was done for now
:
## 2021
*
**Reversort:**
Implementation of a solution in O(N log(N)) using BSTs. (It works!)
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