Last active
December 13, 2022 10:21
-
-
Save pranithan-kang/6a0119e96512eb01574bfe130be37d66 to your computer and use it in GitHub Desktop.
หนังสือเล่มหนึ่งมีเลขหน้าระบุไว้ทุกแผ่นโดยเริ่มจากหน้าที่ 1 โดยหนังสือมีหน้ากระดาษอยู่หนึ่งแผ่นที่ขาดหายไป และเมื่อผลรวมของเลขหน้าทุกหน้าที่เหลือยู่ได้ผลรวมเป็น 999 หน้ากระดาษที่หายไปคือหน้าอะไร
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# โจทย์ | |
# ---- | |
# หนังสือเล่มหนึ่งมีเลขหน้าระบุไว้ทุกแผ่นโดยเริ่มจากหน้าที่ 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