Skip to content

Instantly share code, notes, and snippets.

@pranithan-kang
Last active December 13, 2022 10:21
Show Gist options
  • Save pranithan-kang/6a0119e96512eb01574bfe130be37d66 to your computer and use it in GitHub Desktop.
Save pranithan-kang/6a0119e96512eb01574bfe130be37d66 to your computer and use it in GitHub Desktop.
หนังสือเล่มหนึ่งมีเลขหน้าระบุไว้ทุกแผ่นโดยเริ่มจากหน้าที่ 1 โดยหนังสือมีหน้ากระดาษอยู่หนึ่งแผ่นที่ขาดหายไป และเมื่อผลรวมของเลขหน้าทุกหน้าที่เหลือยู่ได้ผลรวมเป็น 999 หน้ากระดาษที่หายไปคือหน้าอะไร
# โจทย์
# ----
# หนังสือเล่มหนึ่งมีเลขหน้าระบุไว้ทุกแผ่นโดยเริ่มจากหน้าที่ 1 โดยหนังสือมีหน้ากระดาษอยู่หนึ่งแผ่นที่ขาดหายไป และเมื่อผลรวมของเลขหน้าทุกหน้าที่เหลือยู่ได้ผลรวมเป็น 999
# หน้ากระดาษที่หายไปคือหน้าอะไร
# ที่มาของโจทย์: asiamediasoft
# ตีโจทย์
# ----
# ให้ p คือหน้าสุดท้ายของหนังสือ s คือผลรวมของหน้าที่เหลืออยู่ (จากโจทย์คือ 999) และ m คือหน้าที่หายไป
# - กรณีแรก
# หากหนังสือถูกพิมพ์สองหน้าต่อหนึ่งแผ่นกระดาษ จะได้สมการที่จะหาคำตอบคือ
# \frac{p \times (p+1)}{2} = s + m + (m + 1)
# จัดรูปแบบใหม่จะได้เป็น
# p^2 + p - 4m - 2s = 2
# ที่มาของสมการคือ การใช้รูปแบบปิดของผลรวมเลขลำดับ 1..n เป็นฐาน
# - กรณีถัดมา
# หากหนังสือถูกพิมพ์หนึ่งหน้าต่อหนึ่งแผ่นกระดาษ จะได้สมการที่จะหาคำตอบคือ
# \frac{p \times (p + 1)}{2} = s + m
# จัดรูปแบบใหม่จะได้เป็น
# p^2 + p - 2m - 2s = 0
# อาศัยการเขียนโปรแกรมเพื่อวนรอบหาคำตอบโดยใช้ s เป็นขอบบนของเลขหน้าหนังสือ แต่อันที่จริงแล้วค่าขอบบนของเลขหน้ามีค่าน้อยกว่าผลรวม s มาก
# ดังนั้นประสิทธิภาพของโปรแกรมชุดนี้อาจจะสามารถทำให้ดีขึ้นได้อีก แต่ผู้เขียนไม่สามารถคิดได้ว่าจะหาขอบบนที่เหมาะสมได้อย่างไร
# ตอบโดย kang
import pytest
def validate_condition_double_side(p: int, m: int, s: int) -> bool:
"""
Determine that given parameters can be the answer of the problem in case of the book is double side printed
ตัดสินใจว่า parameter ที่รับเข้ามาเป็นคำตอบของโจทย์หรือไม่ ณ ที่นี้หนังสือเล่มนี้พิมพ์สองด้านบนหนึ่งแผ่นกระดาษ
Args:
p (int): Last page - หน้าสุดท้าย
m (int): Missing page - หน้าที่หายไปหน้าแรก
s (int): Sum of existing pages - ผลรวมของหน้าที่เหลืออยู่
Returns:
bool: return True if the parameters can be the answer
คืนค่า True หาก parameter ที่รับเข้ามาเป็นคำตอบ
"""
return p**2 + p - 4 * m - 2 * s == 2
def validate_condition_single_side(p: int, m: int, s: int) -> bool:
"""
Determine that given parameters can be the answer of the problem in case of the book is double side printed
ตัดสินใจว่า parameter ที่รับเข้ามาเป็นคำตอบของโจทย์หรือไม่ ณ ที่นี้หนังสือเล่มนี้พิมพ์ด้านเดียวบนหนึ่งแผ่นกระดาษ
Args:
p (int): Last page - หน้าสุดท้าย
m (int): Missing page - หน้าที่หายไปหน้าแรก
s (int): Sum of existing pages - ผลรวมของหน้าที่เหลืออยู่
Returns:
bool: return True if the parameters can be the answer
คืนค่า True หาก parameter ที่รับเข้ามาเป็นคำตอบ
"""
return p**2 + p - 2 * m - 2 * s == 0
def find_missing_page(s: int, is_double_side: bool) -> tuple:
"""
Finding the missing page from the given sum of existing pages
หาหน้าที่หายไปจากผลรวมของหน้าที่เหลืออยู่
Args:
s (int): Sum of existing pages - ผลรวมของหน้าที่เหลืออยู่
Raises:
ArithmeticError: In case of no answer found, raise this error
โยน ArithmeticError ออกมาในกรณีที่ไม่มีคำตอบ
Returns:
tuple: return the answer of the problem
คืนค่าคำตอบออกมา
"""
step = 2 if is_double_side else 1
for p in range(0, s, step):
for m in range(1, p, step):
if is_double_side:
if validate_condition_double_side(p, m, s):
return (p, m, s)
else:
if validate_condition_single_side(p, m, s):
return (p, m, s)
raise ArithmeticError(
"Cannot find the answer corresponding to given s\nไม่สามารถหาคำตอบจากค่า s ที่ส่งเข้ามาได้"
)
assert find_missing_page(55 - (1 + 2), True) == (10, 1, 52)
assert find_missing_page(55 - (7 + 8), True) == (10, 7, 40)
assert find_missing_page(55 - 1, False) == (10, 1, 54)
assert find_missing_page(55 - 8, False) == (10, 8, 47)
with pytest.raises(ArithmeticError):
find_missing_page(999, True)
print(find_missing_page(55, True))
print(find_missing_page(999, False))
print(find_missing_page(998, True))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment