יום שלישי, 24 בדצמבר 2019

גימטריה בפייתון

המרת מספר לגימטריה
לאחרונה הייתי צריך להמיר ערך מספרי לגימטריה העברית שלו.

דוגמאות:
2   - ב
18  - יח
47  - מז
283 - רפג
411 - תיא


הנה המחלקה והבדיקות שיצרתי:
עריכה: עכשיו המחלקה זמינה להורדה מהירה עם pip. למידע נוסף.

# gematria_test.py

import unittest
from unittest.case import expectedFailure

def main():
    gematria = Gematria()
    for number in range(11000):
        heb_value = gematria.number_to_hebrew(number)
        print(heb_value)
         
class Gematria:
    _heb_letters = [
        ("א"1), 
        ("ב"2), 
        ("ג"3), 
        ("ד"4), 
        ("ה"5), 
        ("ו"6), 
        ("ז"7), 
        ("ח"8), 
        ("ט"9), 
        ("י"10), 
        ("כ"20), 
        ("ל"30), 
        ("מ"40), 
        ("נ"50), 
        ("ס"60), 
        ("ע"70), 
        ("פ"80), 
        ("צ"90), 
        ("ק"100), 
        ("ר"200), 
        ("ש"300), 
        ("ת"400)
        ]

    def number_to_hebrew(selfnumber):
        if number <= 0:
            raise Exception("Number must be bigger than zero")
        if number >= 1000:
            raise Exception("Number bigger than 999 is not supported yet")

        remainder = number
        heb_sum = ""
        while remainder > 0:
            for heb_letter, val in self._heb_letters[::-1]:
                if (val <= remainder):
                    if remainder == 15:
                        heb_sum += "טו"
                        remainder = 0
                    elif remainder == 16:
                        heb_sum += "טז"
                        remainder = 0
                    else:
                        heb_sum += heb_letter
                        remainder -= val
                    break
        return heb_sum

class Test_Gematria(unittest.TestCase): 
    gematria = Gematria()

    def test_simple_num(self):
        self.assertEqual(self.gematria.number_to_hebrew(3), "ג")

    def test_15_num(self):
        self.assertEqual(self.gematria.number_to_hebrew(15), "טו")

    def test_16_num(self):
        self.assertEqual(self.gematria.number_to_hebrew(16), "טז")

    def test_random_tens_num_1(self):
        self.assertEqual(self.gematria.number_to_hebrew(24), "כד")

    def test_random_tens_num_2(self):
        self.assertEqual(self.gematria.number_to_hebrew(77), "עז")

    def test_random_hundreds_num_1(self):
        self.assertEqual(self.gematria.number_to_hebrew(250), "רנ")

    def test_random_hundreds_num_2(self):
        self.assertEqual(self.gematria.number_to_hebrew(499), "תצט")

    def test_bigger_than_800_num(self):
        self.assertEqual(self.gematria.number_to_hebrew(822), "תתכב")

    def test_hundreds_num_that_ends_with_15(self):
        self.assertEqual(self.gematria.number_to_hebrew(515), "תקטו")

    def test_hundreds_num_that_ends_with_16(self):
        self.assertEqual(self.gematria.number_to_hebrew(516), "תקטז")

    def test_zero(self):
        with self.assertRaises(Exception):
            result = self.gematria.number_to_hebrew(0)

    def test_minus(self):
        with self.assertRaises(Exception):
            result = self.gematria.number_to_hebrew(-1)

    def test_too_big(self):
        with self.assertRaises(Exception):
            result = self.gematria.number_to_hebrew(1000)

if __name__== "__main__":
    main()
    # unittest.main() 



פשוט וקל.


יום שישי, 15 בנובמבר 2019

הסבר מתומצת על Casting בשפות מונחות עצמים

נסביר על התכונות הבסיסיות של Casting. כל הדוגמאות יהיו בג'אווה, אבל העקרונות נכונים בעוד הרבה שפות טיפוסיות (Statically Typed Languages) מונחות עצמים.


 Casting

נניח שיש לנו מחלקה משם Animal ויורשת ממנה מחלקה בשם Bird.

מצביע מסוג Animal יכול להצביע על Animal כמובן, אבל הוא יכול להצביע גם על היורשים, ולכן גם על Bird.

    Animal myAnimal1 = new Animal();
    Animal myAnimal2 = new Bird();

פעולה זו נקראת Upcasting, והיא הבסיס לפולימרפיזם.



לאחר ההמרה myAnimal2 לא יכול לקרוא לפונקציות של Bird, מאחר והחיה הזו שכחה שהיא הייתה פעם ציפור. אמנם היא עודנה ציפור וניתן להזכיר לה זאת על ידי Downcasting.


מהו Downcasting?
ההפך של Upcasting. הצבעה על אובייקט עם מצביע ממחלקה שיורשת ממחלקת האובייקט.
Downcasting לעולם יבוא רק לאחר שנעשה Upcasting.

    Bird myBird = (Bird) myAnimal2;

אחרי Downcasting ניתן לקרוא לפונקציות של Bird.

    myBird.fly();





למה Downcasting צריך לכתוב בפירוש ואילו Upcasting לא?
כשיורדים יכולה להיווצר שגיאת זמן ריצה, ולכן ג'אווה בודקת שהמתכנת בטוח לגבי ההחלטה לרדת.
(בשפות ללא הצהרות טיפוסים נגלה את השגיאה רק בשימוש בתכונות הבן שאינן קיימות, ואילו בג'אווה נגלה את זה כבר ברגע ההמרה)

כשעולים לא יכולה להיווצר שגיאת זמן ריצה ולכן אין טעם לציין זאת. (הסיבה היחידה לציין Upcasting היא קצת שיפור של קריאות הקוד, וג'אווה החליטו לוותר על זה)


נדגים:

public class Engineer {
    public void doEngineering() {
        System.out.println("I do some engineering");
    }
}

public class SmartEngineer extends Engineer {
    @Override
    public void doEngineering() {
        System.out.println("I do some engineering (but I am smart!)");
    }
    public void doSmartEngineering() {
        System.out.println("I do some smart engineering");
    }
}

public static void main(String[] args) {
    String userInput = "normal";
        
    Engineer engineer = null;
        
    if (userInput.equals("normal")) {
        engineer = new Engineer();
    }
    else {
        engineer = new SmartEngineer();
    }

    // We can do:
    engineer.doEngineering();

    // We can't do (compilation error):
    // engineer.doSmartEngineering();


    // We can do it but it's risky (If userInput is "normal" we get ClassCastException):

    ((SmartEngineer) engineer).doSmartEngineering();
}


מקווה שהכל ברור.