Skip to content

Instantly share code, notes, and snippets.

@pranithan-kang
Last active August 20, 2023 06:07
Show Gist options
  • Save pranithan-kang/97c9ccc6aff4af705d6853d913d8f86f to your computer and use it in GitHub Desktop.
Save pranithan-kang/97c9ccc6aff4af705d6853d913d8f86f to your computer and use it in GitHub Desktop.
Wine glass solution
1-st pouring
n=1
0.500
2-nd pouring
n=2
1
0.500 0.500
3-rd pouring
n=2
1
1 1
4-th pouring
n=4
1
1 1
0.750 1 0.750
0 0.250 0.250 0
5-th pouring
n=5
1
1 1
1 1 1
0.350 1 1 0.350
0 0.275 0.550 0.275 0
6-th pouring
n=6
1
1 1
1 1 1
1 1 1 1
0 1 1 1 0
0 0.125 0.875 0.875 0.125 0
7-th pouring
n=8
1
1 1
1 1 1
1 1 1 1
0.525 1 1 1 0.525
0 1 1 1 1 0
0 0.087 1 1 1 0.087 0
0 0 0.169 0.919 0.919 0.169 0 0
# problem : wine glass
# source : https://www.facebook.com/groups/ThaiPGAssociateSociety/posts/2392759474268641/
# coded by : kang
from decimal import Decimal
import math
def normalize(layer: list):
return [min(glass, Decimal(1)) for glass in layer]
def pour_wine(a: Decimal):
glasses = None
n = 1
# current layer
cl = [a]
glasses = normalize(cl)
last_layer = False
while not last_layer:
last_layer = True
# next layer
nl: list = []
for i, c in enumerate(cl):
# solution of the new glass in next layer
s = c - 1 if c >= 1 else Decimal(0)
s = s / 2
if s > 0:
last_layer = False
if i == 0:
nl.append(s)
else:
nl[-1] += s
nl.append(s)
i += 1
cl = nl
if not last_layer:
n += 1
glasses += normalize(nl)
return glasses, n
##### unit-tests #####
(glasses, n) = pour_wine(Decimal(0.5))
assert glasses == [Decimal(0.5)]
assert n == 1
(glasses, n) = pour_wine(Decimal(2))
assert glasses == [Decimal(1), Decimal("0.5"), Decimal("0.5")]
assert n == 2
(glasses, n) = pour_wine(Decimal(3))
assert glasses == [Decimal(1), Decimal(1), Decimal(1)]
assert n == 2
(glasses, n) = pour_wine(Decimal(6))
assert glasses == [
Decimal(1),
Decimal(1), Decimal(1),
Decimal("0.75"), Decimal(1), Decimal("0.75"),
Decimal(0), Decimal("0.25"), Decimal("0.25"), Decimal(0),]
assert n == 4
(glasses, n) = pour_wine(Decimal("9.8"))
assert glasses == [
Decimal(1),
Decimal(1), Decimal(1),
Decimal(1), Decimal(1), Decimal(1),
Decimal('0.35'), Decimal(1), Decimal(1), Decimal('0.35'),
Decimal('0'), Decimal('0.275'), Decimal('0.550'), Decimal('0.275'), Decimal('0')]
assert n == 5
def display_glasses(glasses: list, n: int):
print(f"n={n}")
# deep copy
glasses = list(glasses)
spacer = "\t"
# NOTE: for debugging purpose
# spacer = "s"
# normalized n
nn = n + 1 if n % 2 == 0 else n
for i in range(1, n+1):
# partial glasses (layer)
pg = glasses[:i]
# leading spaces between layer
ls = (spacer * 2 * int(math.floor((nn - i)/2)))
if len(pg) % 2 == 0:
ls += spacer
print(ls, end="")
for g in pg:
format_string = "%.3f" if 0 < g < 1 else "%d"
print(format_string % g, end=spacer*2)
print("\n")
glasses = glasses[i:]
# NOTE: for debugging purpose
# glasses == [
# Decimal(1),
# Decimal(1), Decimal(1),
# Decimal(1), Decimal(1), Decimal(1),
# Decimal('0.35'), Decimal(1), Decimal(1), Decimal('0.35'),
# Decimal('0'), Decimal('0.275'), Decimal('0.550'), Decimal('0.275'), Decimal('0')]
# n = 5
# display_glasses(glasses, n)
# glasses = [Decimal(1), Decimal(1), Decimal(1)]
# n = 2
# display_glasses(glasses, n)
##### real application #####
print("1-st pouring")
display_glasses(*pour_wine(Decimal(0.5)))
print("2-nd pouring")
display_glasses(*pour_wine(Decimal(2)))
print("3-rd pouring")
display_glasses(*pour_wine(Decimal(3)))
print("4-th pouring")
display_glasses(*pour_wine(Decimal(6)))
print("5-th pouring")
display_glasses(*pour_wine(Decimal("9.8")))
print("6-th pouring")
display_glasses(*pour_wine(Decimal("15")))
print("7-th pouring")
display_glasses(*pour_wine(Decimal("23.4")))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment