חידת C

עריסטו

Active member
חידת C

כיתבו תוכנית בשפת C או ++C שהפלט שלה למסך הוא התוכנית עצמה. לתוכנית אסור לקרוא את עצמה ממקור חיצוני (כגון קובץ).
 

Ghostmize

New member
לאדע C

בPASCAL גם תיתכן תוכנית כזו
 

slallum

New member
אם לא פותרים את החידה הזו

בבקשה תן את הפיתרון, מעניין ביותר איך אפשר לפתור את זה :)
 
גם בשפת MUMPS זה לא מסובך,

אם כי נדרשת מידה מסויימת של זהירות. הרעיון הוא, שכותבים את כל התכנית פעמיים - בפעם השניה כשורת ליטרלים המכילים את פקודות החצי הראשון. אבל, במקום גרשיים, המסבכים את העניין, כותבים בליטרלים תו אחר כלשהו, והתוכנית גם יודעת לתרגם אותו לגרשיים. אגב, בשפת MUMPS יש גם גישה ישירה לטקסט התוכנית, ואפילו פקודה אחת להדפסת כל הטקסט. אבל כמובן לא חוכמה להשתמש בזה.
 

slallum

New member
לא הבנתי בדיוק

אני משער שזה קרה כתוצאה מכך שאין לי מושג מה זה MUMPS וליטרלים :) הסבר בבקשה לטיפשים שבנינו?
 
גם לא כתבתי בדיוק, רק בקווים כלליים

ולא נראה לי שבחירת השפה מהותית. "ליטרל" - משהו שמוגדר ישירות. למשל, במקום לכתוב בתכנית (בכל שפה שהיא) שם של משתנה המכיל ערך מסויים, במקרים רבים רבים כותבים ישירות את הערך הזה. למשל, כאשר כותבים: a = a + 5 הביטוי "5" הוא ליטרל. אני התכוונתי לליטרלים מסוג אחר, לסטרינגים, מחרוזות. למשל:
:זוהי פקודה Write a+b :וזו סתם מחרוזת x = "Write a+b" .ש"במקרה" מכילה את הטקסט של פקודה מסויימת​
הרעיון הפרימיטיבי שלי (עשיתי את זה מזמן-מזמן, ואולי יש דרכים טובות יותר) הוא בערך כזה. כל התכנית נכתבת פחות או יותר פעמיים, פעם כפקודות, ופעם אחת כבניית סטרינגים המכילים פקודות אלו. ה"עוקץ" הוא בתו " ("גרשיים"), כי לשם תיאורו צריך לכתוב אותו פעמיים, ואז יוצא שצריך בעצם לכתוב אותו 4 פעמים, אבל בעצם 8, ובקיצור לא יוצאים מזה. פיתרון אפשרי לזה הוא קידוד התו הזה, בסטרינגים המתארים את הפקודות, לתו אחר. ושוב: זה רק הרעיון הכללי, בלי פירוט.
 

inbal76

New member
אבל הגרשיים זו לא הבעיה היחידה

אפילו לא העיקרית.הבעיה העיקרית היא הרקורסיביות... אתה צריך לכתוב פקודה שמדפיסה מחרוזת שכוללת את עצמה. כלומר אם יש לך בתוכנית פקודת
Write a+b​
אז לא מספיק שתהיה המחרוזת
x = "Write a+b"​
כי צריך להדפיס גם את זה, אז צריך מחרוזת
y = "x = "Write a+b""​
וכן הלאה... לא יודעת MUMPS, אולי שם יש דרך פשוטה להתמודד עם זה, אבל בשפות שאני מכירה אין. כלומר יש טריק כלשהו, אני זוכרת שפעם איזה מרצה הראה לנו את זה ב-C, ואם אני זוכרת נכון יש אפילו אתר שלם של דוגמאות לתוכניות שמדפיסות את עצמן. אבל אני לא זוכרת איך עושים את זה ואין לי כוח לחפש.
 
התכנית ב-MUMPS

PSelf ; Printing itself ; [ 07.07.2005 ] ;-----------------* s x(1)=" w ~PSelf ; Printing itself ; [ 07.07.2005 ]~,!" s x(2)=" w ~ ;-----------------*~,!" s x(3)=" s gr=~~~~,tild=$c(126)" s x(4)=" s m=~ s x(~" s x(5)=" s n=~)=~" s x(6)=" f i=1:1:8 w m,i,gr,x(i),gr,!" s x(7)=" f i=1:1:8 w $tr(x(i),tild,gr),!" s x(8)=" q" w "PSelf ; Printing itself ; [ 07.07.2005 ]",! w " ;-----------------*",! s gr="""",tild=$c(126) s m=" s x(" s n=")=" f i=1:1:8 w m,i,gr,x(i),gr,! f i=1:1:8 w $tr(x(i),tild,gr),! q​
ומכיוון ששתי השורות הראשונות הן רק "ליופי", אפשר בעיקרון להעיף אותן, ומתקבל:
s x(1)=" s gr=~~~~,tild=$c(126)" s x(2)=" s m=~ s x(~" s x(3)=" s n=~)=~" s x(4)=" f i=1:1:8 w m,i,gr,x(i),gr,!" s x(5)=" f i=1:1:8 w $tr(x(i),tild,gr),!" s x(6)=" q" s gr="""",tild=$c(126) s m=" s x(" s n=")=" f i=1:1:6 w m,i,gr,x(i),gr,! f i=1:1:6 w $tr(x(i),tild,gr),! q​
הסברים: s - הענק ערך למשתנה. w - הדפס. f - בצע מספר פעמים עבור שורת ערכים של משתנה. ()c$ - תו. ()tr$ - "תרגם" ("גל" ל"גרשיים").
 
תיקון

PSelf ; Printing itself ; [ 07.07.2005 ] ;-----------------* s x(1)=" w ~PSelf ; Printing itself ; [ 07.07.2005 ]~,!" s x(2)=" w ~ ;-----------------*~,!" s x(3)=" s gr=~~~~,tild=$c(126)" s x(4)=" s m=~ s x(~" s x(5)=" s n=~)=~" s x(6)=" f i=1:1:8 w m,i,n,gr,x(i),gr,!" s x(7)=" f i=1:1:8 w $tr(x(i),tild,gr),!" s x(8)=" q" w "PSelf ; Printing itself ; [ 07.07.2005 ]",! w " ;-----------------*",! s gr="""",tild=$c(126) s m=" s x(" s n=")=" f i=1:1:8 w m,i,n,gr,x(i),gr,! f i=1:1:8 w $tr(x(i),tild,gr),! q​
 
אולי כך יותר ברור

! - עבור לשורה חדשה. אולי יש ל-MUMPS יתרון "לא הוגן" - הפונקציה המאפשרת המרת תווים? אם כי זה לא עקרוני - אף אחד לא מפריע לכתוב ב-C לולאה.
PSelf ; Printing itself ; [ 07.07.2005 ] ;-----------------* Set x(1)=" Write ~PSelf ; Printing itself ; [ 07.07.2005 ]~,!" Set x(2)=" Write ~ ;-----------------*~,!" Set x(3)=" Set gr=~~~~,tild=$c(126)" Set x(4)=" Set m=~ Set x(~" Set x(5)=" Set n=~)=~" Set x(6)=" For i=1:1:8 Write m,i,n,gr,x(i),gr,!" Set x(7)=" For i=1:1:8 Write $Translate(x(i),tild,gr),!" Set x(8)=" Quit" Write "PSelf ; Printing itself ; [ 07.07.2005 ]",! Write " ;-----------------*",! Set gr="""",tild=$c(126) Set m=" Set x(" Set n=")=" For i=1:1:8 Write m,i,n,gr,x(i),gr,! For i=1:1:8 Write $Translate(x(i),tild,gr),! Quit​
 

inbal76

New member
יפה!

לא מכירה MUMPS אבל זה נראה מאוד דומה לאחת התוכניות שראיתי ב-C. למרות שב-C יש דרך הרבה יותר אלגנטית וקצרה (ואולי גם ב-MUMPS...)
 

inbal76

New member
יכולה, אבל זה יקלקל לכולם, לא?

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

אז זה לא מעניין, ואם זה משהו אוניברסלי במהותו - שלחי לי בבקשה במסר.
 

slallum

New member
הפתרון הזה יוצר לולאה אינסופית

כי תצטרך לכתוב את הפקודות שכותבות את התוכנית, ואז תצטרך לכתוב את הפקודות שכותבות את הפקודות שכותבות את התוכנית וכן הלאה..
 

עריסטו

Active member
הערה על דבריו של טלמון סילבר

"אגב, בשפת MUMPS יש גם גישה ישירה לטקסט התוכנית, ואפילו פקודה אחת להדפסת כל הטקסט. אבל כמובן לא חוכמה להשתמש בזה." פתרון כזה באמת לא נחשב... למשל, בשפת בייסיק הישנה היתה פקודה בשם LIST שהדפיסה למסך את התוכנית. זה לא נחשב פתרון (לכתוב תוכנית המורכבת רק מהמילה LIST - הפלט של התוכנית הזו למסך הוא LIST), כי זה נחשב קריאה של התוכנית ממקור חיצוני (במקרה זה - הזכרון). עוד דבר: ב - C אי אפשר לכתוב תוכנית ריקה. אני לא יודע אם בפסקל אפשר לכתוב תוכנית כזו. אם אפשר - זה פותר את הבעיה, כי גם הפלט למסך הוא ריק, אבל גם זה לא נחשב פתרון.
 

עריסטו

Active member
טוב

אם לא יפתרו תוך מספר ימים אתן פתרון ב - C ובפסקל. בינתיים נסה לפתור לבד... העזר בדבריו של טלמון סילבר.
 

Ghostmize

New member
ממממ..נתקעתי :)

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

Ghostmize

New member
אמרתי אחד ויחיד וכתבתי שניים../images/Emo6.gif

זה מה שקורה שחושבים תוך כדי שכותבים
 
למעלה