راه
۵ کیو· متوسط رو به بالامتوسطPYTHON۴ ثانیه · ۲۵۶ مگابایت

عدد جادویی (Strint)

در این تمرین، شما یک کلاس نوع داده‌ی جدید ایجاد خواهید کرد که از کلاس داخلی int در پایتون ارث‌بری می‌کند. هدف این است که رفتار پیش‌فرض اعداد صحیح را برای مقایسه، جمع، تفریق و نمایش تغییر دهید و یک نوع داده‌ی جدید با قوانین خاص بسازید.


کلاس Strint


عملیات مقایسه‌ای

مقایسه‌ی دو شیء Strint تنها بر اساس رقم یکان آن‌ها انجام می‌شود.

Strint اول کوچک‌تر از Strint دوم است، اگر رقم یکان Strint اول کوچک‌تر از رقم یکان Strint دوم باشد.

مثال: Strint(84) < Strint(39) نتیجه می‌دهد True (زیرا رقم یکان ۸۴ یعنی ۴ کوچک‌تر از رقم یکان ۳۹ یعنی ۹ است).

Strint اول بزرگ‌تر از Strint دوم است، اگر رقم یکان Strint اول بزرگ‌تر از رقم یکان Strint دوم باشد.

مثال: Strint(39) > Strint(84) نتیجه می‌دهد True (زیرا رقم یکان ۳۹ یعنی ۹ بزرگ‌تر از رقم یکان ۸۴ یعنی ۴ است).

Strint اول مساوی Strint دوم است، اگر رقم یکان آن‌ها مساوی باشد.

مثال: Strint(84) == Strint(34) نتیجه می‌دهد True (زیرا رقم یکان هر دو ۴ است). مثال: Strint(12) == Strint(58) نتیجه می‌دهد False (زیرا رقم یکان آن‌ها یکسان نیست).

مقایسه‌های <=, >= و != نیز باید بر اساس همین منطق رقم یکان عمل کنند.


عملیات ریاضی

جمع دو شیء Strint با تبدیل آن‌ها به نمایش رشته‌ای و الحاق (concatenation) نمایش رشته‌ای شیء دوم به انتهای نمایش رشته‌ای شیء اول انجام می‌شود. نتیجه‌ی عمل جمع باید یک شیء Strint جدید باشد.

مثال: Strint(84) + Strint(39) نتیجه می‌دهد Strint(8439). مثال: Strint(39) + Strint(84) نتیجه می‌دهد Strint(3984).

تفاضل دو شیء Strint به این صورت است که نمایش رشته‌ای شیء دوم از انتهای نمایش رشته‌ای شیء اول حذف می‌شود.

⚠️ شرط معتبر بودن تفریق: تفریق تنها زمانی معتبر است که نمایش رشته‌ای شیء اول با نمایش رشته‌ای شیء دوم به پایان برسد.

  • اگر نمایش رشته‌ای شیء اول با نمایش رشته‌ای شیء دوم به پایان نرسد، باید یک استثنا از نوع ValueError با پیام دقیق 'The subtraction is not valid!' پرتاب شود.
  • اگر تفریق معتبر بود، نمایش رشته‌ای شیء دوم از انتهای نمایش رشته‌ای شیء اول حذف می‌شود. رشته‌ی باقی‌مانده به عدد صحیح تبدیل شده و نتیجه در قالب یک شیء Strint جدید بازگردانده می‌شود.
  • اگر پس از حذف، رشته‌ی باقی‌مانده خالی بود (مانند تفریق Strint(123) - Strint(123) که نتیجه‌اش رشته خالی می‌شود)، نتیجه باید Strint(0) در نظر گرفته شود.

مثال‌های معتبر: Strint(8439) - Strint(39) → Strint(84) Strint(8439) - Strint(8439) → Strint(0) Strint(8439) - Strint(439) → Strint(8) مثال نامعتبر: Strint(8439) - Strint(43) → ValueError (زیرا 8439 با 43 پایان نمی‌پذیرد)


طول

طول یک شیء Strint برابر با تعداد ارقام در نمایش رشته‌ای آن است.

مثال: len(Strint(232425)) نتیجه می‌دهد 6. len(Strint(0)) نتیجه می‌دهد 1.


فراخوانی

هنگام فراخوانی یک شیء Strint با استفاده از ()، باید عدد با استفاده از ارقام فارسی نمایش داده شود.

مثال: Strint(232425)() باید خروجی دهد: ۲۳۲۴۲۵ مثال: Strint(10)() باید خروجی دهد: ۱۰


نکته: صفرهای بی‌ارزش

مانند اعداد صحیح معمولی، صفرهای سمت چپ در نمایش عددی بی‌اهمیت هستند و نباید تأثیری روی اجرای توابع داشته باشند.

مثال: Strint(007) معادل Strint(7) است و هر دو مقدار عددی ۷ را دارند.


💡 چالش‌های حل تمرین

⚠️ چرا کلاس Strint از int ارث برده‌است؟

این باعث می‌شود اشیاء Strint به‌طور خودکار دارای یک مقدار عددی صحیح باشند و بتوانند در بسیاری از جاهایی که اعداد صحیح عادی استفاده می‌شوند، به کار روند (البته با رفتارهای عملیاتی که شما تعریف می‌کنید).

⚠️ چرا این کلاس، تابع سازنده ندارد؟ آیا باید خودم تابع سازنده را تعریف کنم؟

در این کلاس نیازی به تعریف تابع سازنده نیست. خود شیء، حامل مقدار عددی خود خواهد بود. دلیل این امر، همان ارث‌بری از کلاس int است.

⚠️ نوع مقدار ذخیره‌شده در شیء دقیقاً چیست، عدد یا رشته؟

از آن‌جا که این کلاس از کلاس int ارث می‌برد، نوع داده‌ی ذخیره‌شده در آن، عدد صحیح خواهد بود. برای پیاده‌سازی برخی متدها (مانند جمع و تفریق) نیاز خواهید داشت که مقدار عددی self و other را به نمایش رشته‌ای تبدیل کنید و سپس عملیات رشته‌ای مورد نیاز Strint را انجام دهید. در پایان عملیات، اگر نتیجه یک عدد بود، باید آن را دوباره به int تبدیل کرده و برگردانید.

⚠️ چگونه ارقام انگلیسی را به فارسی تبدیل کنم؟

برای تبدیل ارقام لاتین به فارسی در متد __str__، می‌توانید نمایش رشته‌ای عدد (که به‌صورت پیش‌فرض با ارقام لاتین است) را پیمایش کرده و هر رقم را با معادل فارسی آن جایگزین کنید. استفاده از یک دیکشنری برای نگاشت ارقام لاتین ('0' تا '9') به ارقام فارسی ('۰' تا '۹') رویکرد مناسبی است.

در نظر داشته باشید که نمی‌توانید از کتابخانه‌هایی که برای این کار ساخته شده‌اند استفاده کنید؛ زیرا این کتابخانه‌ها نیاز به نصب جداگانه خواهند داشت.


💡 راهنمایی نهایی

ساختار کلی کلاس Strint به این شکل است:

python
class Strint(int):
    def _units(self, other):
        return abs(int(self)) % 10, abs(int(other)) % 10

    def __lt__(self, other):
        a, b = self._units(other)
        return a < b

    def __le__(self, other):
        a, b = self._units(other)
        return a <= b

    def __gt__(self, other):
        a, b = self._units(other)
        return a > b

    def __ge__(self, other):
        a, b = self._units(other)
        return a >= b

    def __eq__(self, other):
        a, b = self._units(other)
        return a == b

    def __ne__(self, other):
        a, b = self._units(other)
        return a != b

    __hash__ = int.__hash__

    def __add__(self, other):
        return Strint(str(int(self)) + str(int(other)))

    def __sub__(self, other):
        s, t = str(int(self)), str(int(other))
        if not s.endswith(t):
            raise ValueError("The subtraction is not valid!")
        rest = s[:len(s) - len(t)]
        return Strint(int(rest) if rest else 0)

    def __len__(self):
        return len(str(int(self)))

    def __call__(self):
        return str(int(self)).translate(str.maketrans("0123456789", "۰۱۲۳۴۵۶۷۸۹"))
  • __lt__ و __eq__ ← مقایسه بر اساس رقم یکان (با % 10)
  • __add__ ← الحاق رشته‌ها و بازگشت Strint جدید
  • __sub__ ← بررسی endswith() و حذف از انتها
  • __len__ ← تعداد ارقام با len(str(self))
  • __call__ ← تبدیل ارقام لاتین به فارسی با دیکشنری
  • استفاده از abs() برای مدیریت اعداد منفی در مقایسه
  • بررسی endswith() برای اعتبارسنجی تفریق

✅ این تمرین را در ویرایشگر خود پیاده‌سازی کنید. به یاد داشته باشید که کلاس Strint از int ارث‌بری می‌کند و نیازی به تعریف تابع سازنده ندارد.

نمونه‌ها

ورودی نمونه ۱
[Strint(84) < Strint(39), Strint(39) > Strint(84), Strint(84) == Strint(34), Strint(12) == Strint(58)]
خروجی نمونه ۱
[True, True, True, False]
ورودی نمونه ۲
[Strint(39) > Strint(84), Strint(15) <= Strint(25), Strint(19) >= Strint(91), Strint(10) != Strint(20)]
خروجی نمونه ۲
[True, True, True, False]
ورودی نمونه ۳
[Strint(11) != Strint(22), Strint(90) >= Strint(1), Strint(5) <= Strint(16)]
خروجی نمونه ۳
[True, False, True]
ورودی نمونه ۴
Strint(84) + Strint(39)
Strint(39) + Strint(84)
type(Strint(1) + Strint(2)).__name__
خروجی نمونه ۴
8439
3984
'Strint'
ورودی نمونه ۵
Strint(8439) - Strint(39)
Strint(8439) - Strint(8439)
Strint(8439) - Strint(439)
type(Strint(8439) - Strint(39)).__name__
خروجی نمونه ۵
84
0
8
'Strint'
ورودی نمونه ۶
try:
    Strint(8439) - Strint(43)
except ValueError as error:
    print(error)
خروجی نمونه ۶
The subtraction is not valid!
ورودی نمونه ۷
[len(Strint(232425)), len(Strint(0)), len(Strint(int("007")))]
خروجی نمونه ۷
[6, 1, 1]
ورودی نمونه ۸
Strint(232425)()
Strint(10)()
خروجی نمونه ۸
'۲۳۲۴۲۵'
'۱۰'

برای نوشتن پاسخ و دریافت امتیاز، ابتدا وارد حساب شوید.

ورود