אתגר (בשבילי) בפייתון

  • פותח הנושא et28
  • פורסם בתאריך

et28

New member
אתגר (בשבילי) בפייתון

אני רוצה לאתגר את עצמי ונתקלתי באתגר שלא מצליח לחשוב על פתרון שעובד...
המטרה: תכנית מקבלת מהמשתמש משפט והתוכנית צריכה לספור כמה פעמים כל תו מופיע. למשל, למחרוזת "Hello world", הפלט יהיה:
H 1
e 2
l 3
o 2
w 1
r 1
d 1
מה שאני מנסה לעשות זה לבנות רשימה שהערכים שלה כרגע זה 0, וכל אות תוסיף במיקום של האות (לפי סדר ה- abc) 1, כך שיש ספירה. זה הקוד:
קוד:
str = "Hello world"
str = str.str.lower()
cnt_char = [0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0)

for char in str:
    cnt_char[char] += 1

print cnt_char
בעצם מה שאני רוצה במקרה הזה, בשביל האות הראשונה (h) שברשימה במיקום 8 (או 7 לפי פייתון) יתווסף ל- 0 1, כלומר הערך יהיה 1. במקרה של האות l (האות L) יהיה 2 בגלל שבהתחלה יש תוספת של אחד ואז עוד אחד, כך שזה 2.

ההודעה שאני מקבל:
קוד:
Traceback (most recent call last):
  File "C:/Users/Et/PycharmProjects/tirgul.py/tirgul.py", line 7, in <module>
    cnt_char[char] += 1
TypeError: list indices must be integers, not str
איך בעצם אני סופר כמות תווים במחרוזת?
 

otherside3

New member
ניסיון עזרה: לא בטוח על פייתון, אבל אם זה כמו ב-c

ובהנחה שאתה יודע כי הקלט שלך הוא עם אותיות קטנות בלבד, אז אתה יכול לנסות
char - 'a'
שממיר לך את ה-char למספר בין 0 ל-25 ע"פ הערך האסקי שלו ביחס לערך האסקי של a..

שים לב שאם יש לך תו שהוא לא אות קטנה, אז אתה תמצא את עצמך חורג מהגבולות...
 

BravoMan

Active member
זה לא יעבוד ב-Python.

בניגוד ל-C גרש בודד אינו מסמן תו בודד ב-Python, וגם אין בשפה טיפוס char שהשפה מתייחסת אליו כ-int קטן.
&nbsp
דוגמת הקוד שלך ב-Python מנסה לבצע חיסור בין מחרוזות (str) מה שכמובן יגרור שגיאה.
 

BravoMan

Active member
אם אתה רוצה לאתגר את עצמך, למה אתה מפיל את הפתרון עלינו?

נראה כאילו אתה מנסה לכתוב פתרון לפי כללים שהמצאת בעצמך, ולא לפי כללי שפת Python.
&nbsp
למה ואיך החלטת שאתה יכול להשתמש באותיות בתור אינדקס לתוך רשימה?
&nbsp
אני אתן לך רמז:
הפתרון הכי פשוט יהיה להשתמש במה שהסברתי לך בשרשור הקודם שפתחת פה.
התרגיל הזה הוא תשובה מצוינת לשרשור ההוא.
&nbsp
אפשר כמובן לפתור גם תוך שימוש ברשימה, אבל אז תצטרך ללמוד איך מחשב מייצג תווים.
 

et28

New member
תגובה, והמשך אתגר :)

לא מפיל את הפתרון עליך. בהתחלה ניסיתי באמת עם מילונים, אבל כשישנתי על התגובה שלך (כן, כן, ראיתי אותה אתמול בלילה) אז קמתי עם פתרון אחר ממה שעשיתי וזה עובד!!! הקוד:
קוד:
str = "I am the best because i solved my challenge"
cnt_char= {"a":0,"b":0,"c":0,"d":0,"e":0,"f":0,"g":0,"h":0,"i":0,"j":0,
           "k":0,"l":0,"m":0,"n":0,"o":0,"p":0,"q":0,"r":0,"s":0,"t":0,
           "u":0,"v":0,"w":0,"x":0,"y":0,"z":0," ":0}

for char in str.lower():
    cnt_char[char] += 1

for key,value in cnt_char.items():
    if value!=0:
        print key, value
האמת? הגיוני לעשות את זה במילונים. אבל, אמרת שאשר לעשות את זה ברשימות... אז הנה אני מאתגר את עצמי שוב: איך אני עושה את אותו האתגר, הפעם בלי מילון אלא עם רשימות?
מה שאני לא מבין ברשימות, למה זה יוצר לי הודעת שגיאה? איך אני באותה רשימה עושה גם תו ("a") וגם מספר (0), ולאחר מכן מוסיף למספר 1? כפי שהראיתי בקוד הראשוני זה נותן קוד שגיאה.

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

BravoMan

Active member
יופי. מכאן אני יכול להסביר לך את מה שאתה צריך:

ההבדל בין מילון לרשימה זה איך הם מסדרים את הנתונים:
"מילון" מאפשר לך לתת כל תווית שאתה רוצה לנתון, ואז למצוא את הנתון לפי אותה תווית.
&nbsp
וזה מה שעשית בתרגיל הנ"ל.
&nbsp
רשימה לאומת זאת, מאחסנת נתונים ברצף, ומאפשרת גישה אליהם אך ורק דרך "אינדקס" המספר הרציף לפיו אחסנת.
האינדקס מתחיל ב-0 ונגמר ב-"גודל רשימה פחות אחד".
&nbsp
עכשיו, אתה מעוניין לתת לכל אינדקס משמעות: לשייך אליו אות, כדי לדעת למשל שתא באינדקס 0 מאחסן את כמות ההופעות של אות a.
&nbsp
כלומר, אתה עכשיו רוצה לעשות בעצמך חלק מהעבודה שמילון עשה עבורך!
&nbsp
אז אתה צריך לחשוב על שיטה שתתרגם אות, למספר בצורה שעונה על התנאים הבאים:
1. עקבית - אות ספציפית תמיד תתורגם לאותו מספר בדיוק
2. חד חד ערכית - לא יהיו שתי אותיות שונות שיתורגמו לאותו מספר
3. רציפה - אותיות עוקבות לפי סדר הא-ב יתורגמו למספרים עוקבים בהפרשים של 1.
4. שמתחילה ב-0 כלומר, אות a תתורגם תמיד ל-0.
&nbsp
כאן, המחשב כבר עשה עבורך חלק מהעבודה, כי מחשב מייצג הכל בעזרת מספרים.
הא-ב האנגלי מיוצג לפי טבלת ASCII (יש דרכי ייצוג אחרות, וזאת קצת ישנה, אבל היא מתאימה ונכונה לתרגיל שלנו).
&nbsp
הטבלה הזו עונה על תנאים 1 עד 3: כל אות בה מיוצגת ע"י מספר ייחודי, והאותיות מסודרות לפי רצף הא-ב וכך גם המספרים.
הבעיה היחידה היא ש-a לא ממוקמת על 0.
&nbsp
אז, מה שאתה צריך זה לעשות 3 דברים:
1. לברר איך ב-python מקבלים את הייצוג המספרי של אות.
2. לבצע חישוב ש-"יזיז" (ינרמל) את המספרים של האותיות כך ש-a תתחיל ב-0.
3. להשתמש בתוצאות של 1 ו-2 בתור אינדקס לרשימה.
&nbsp
אני אחסוך לך את 1 - תקרא על פונקציה ord.
לגבי 2, שים לב! רווח אינו נמצא ברצף האותיות, לכן תצטרך להתחשב בזה כשאתה כותב את הקוד שלך.
 

BravoMan

Active member
נקודה קטנה לגבי הפתרון שלך:

אתחלת את המילון ידנית, זה הרבה כתיבה מיותרת.
&nbsp
אם תקרא את התיעוד של "מילון" תראה שיש לו מתודה שימושית:
https://docs.python.org/2/library/stdtypes.html#mapping-types-dict
&nbsp
המתודה היא get.
מתודה זו מקבל 2 פרמטרים: הראשון תווית של הערך שאתה רוצה לשלוף, והשנייה ערך ברירת מחדל.
אם אתה משתמש במתודה הזו במקום סוגריים מרובעים [], הקוד שלך לא יקבל שגיאה גם אם לא קיים ערך עם תווית שאתה מבקש.
במקום זה, המתודה תחזיר את הערך ברירת מחדל שנתת לה.
&nbsp
נסה לחשוב איך להשתמש ב-get כדי לחסוך לעצמך את הכתיבה של כל האלפבת האנגלי, ועל הדרך למנוע מקוד שלך לקרוס אם במחרוזת שאתה בודק יש ספרות או סימני פיסוק.
&nbsp
(כי כרגע מספיק לשים נקודה בסוף משפט והקוד שלך ייפול עם שגיאה!)
 

et28

New member
וואו, נתת לי הרבה שיעורי בית :)

זה אומר שאני אשב על זה בימים הקרובים, ואנסה לפתור את זה :)
תודה רבה!
 

BravoMan

Active member
אתה חושב שזה הרבה?

למעשה, יש עוד שתי דרכים לפתור את התרגיל עם מילון בלי לאתחל את המילון, ועוד דרך לאתחל את המילון אבל תוך כתיבה של פחות תווים.
&nbsp
אחת הדרכים היא נושא נפרד מהמילון - טיפול ב-"חריגות" (exceptions).
&nbsp
אם זה באמת מעניין אותך, תעמיק בלימוד המילון ותמצא את הדרכים האלה.
 

et28

New member
תודה :) מקציב לעצמי שבוע לכל הלמידה הזו,

מקווה שאני אעמוד ביעד :)
 
למעלה