שיעור זה מכין לחלק הכנס שבו קיבלת קוד מומצא ואתה צריך להבין מה הוא עושה. Dry Run שיטתי, Pattern Matching מהיר, וניהול זמן תחת לחץ — כל הכלים במקום אחד.
כתיבת קוד = מתחיל מבעיה, כותב פתרון. הנדסה לאחור = מתחיל מקוד מוכן — מוצא מה הוא עושה. זה בדיוק מה שנדרש במחשבון קרב.
💡 אנלוגיה — Dry Run כניתוח מתכון
קיבלת עוגה ואתה רוצה לדעת מה בה. אתה לא מכין עוגה — אתה טועם, מריח, ומנסה להסיק: "יש כאן קמח, חמאה, ב-180 מעלות..." Dry Run = טעימה שיטתית של הקוד. Symbol Table = הרשימה שאתה כותב.
4 רמות קושי בשיעור
רמה
סוג שאלה
זמן מטרה
⭐ רמה 1
לולאות פשוטות, Symbol Table בסיסי
~2 דקות
⭐⭐ רמה 2
לולאות מקוננות, תנאים, פלטים מרובים
~3 דקות
⭐⭐⭐ רמה 3
רקורסיה, Multi-Function, Call Stack
~5 דקות
⭐⭐⭐⭐ רמה 4
כנס-סטייל: כל הנ"ל + Edge Cases + שאלות מרובות
7–10 דקות
🎯 מפרטים מהירים — 4 שפות
Zenith:LET/SET · FOR i=a TO b · WHILE · FUNC/RETURN · PRINT · MOD · ^ Kova:var · x:= · @ i in a..b · @@ cond · fn/ret · >> TalonScript:x<~ · iter# i[a:b] (inclusive) · ?! · say · fn/ret · %% AxonLang:DECL/UPDATE · EACH OVER a->b (exclusive!) · UNTIL · WHEN/OTHERWISE · DISPLAY
⚠️ inclusive vs exclusive — ההבדל הקריטי
TalonScript iter# i [2:6] = i=2,3,4,5,6 (כולל 6!) · AxonLang EACH i OVER 2->6 = i=2,3,4,5 (לא כולל 6!) · Zenith/Kova = inclusive בשני הקצוות.
✏תרגול — מבוא3 שאלות
שאלה 1
AxonLang: EACH i OVER 0->3 — כמה iterations?
✓ תשובה: א) 3 iterations — AxonLang EACH OVER a->b = exclusive. 0->3 = i=0,1,2. לא כולל 3!
שאלה 2
TalonScript: iter# i [2:6] — כמה iterations?
✓ תשובה: ד) 5 — TalonScript inclusive: i=2,3,4,5,6. AxonLang OVER 2->6 = 4 iterations (לא 6). ← ההבדל הכי חשוב!
שאלה 3
מה Pattern Matching בהקשר של Dry Run?
✓ תשובה: ג) — Pattern Matching = לראות result *= i ולדעת: זה פקטוריאל. לא צריך Dry Run מלא — מאיץ ומכוון.
// רמה 1 — 3 קטעי קוד
רמה ⭐ — לולאות בסיסיות
מטרה: 2 דקות לקטע קוד. Symbol Table פשוט. תרגל עד שזה אוטומטי.
קוד 1.1 — Zenith: פקטוריאל
// שפת Zenith — שאלות:
// א) מה הפלט? ב) מה עושה הקוד?
LET n = 5
LET result = 1
FOR i = 1 TO n
SET result TO result * i
END FOR
PRINT result
Pattern: result=1; result=result*i → מכפיל רצף → פקטוריאל
קוד 1.2 — Kova: לולאה עם תנאי
// שפת Kova — שאלות:
// א) מה הפלט? ב) מה ערך x אחרי iteration ה-3?
var x : num
var y : num
x := 100
y := 0
@ i in 1..6 {
? x % 3 == 0 { y := y + x }
x := x - 7
}
>> y
Zenith: FOR i = 5 TO 3: PRINT i. END FOR. PRINT "done" — מה הפלט?
✓ תשובה: א) "done" בלבד — start=5 > end=3 → לולאה לא רצה כלל! Edge Case קלאסי.
📌 סיכום ביניים — לולאות בסיסיות
עד כאן שלושה כלים: (1) לרשום את המשתנים בטבלה לפני הסיבוב הראשון, (2) לבדוק אם הגבול כולל את הקצה, (3) לזהות את הצעד — +1 הוא לינארי, *2 או *3 מקצר את מספר הסיבובים דרמטית.
לפני שממשיכים לרמה הבאה: קחו נשימה, ובדקו שאתם יודעים לענות "כמה פעמים רץ הגוף?" בלי להריץ הכול בראש.
// רמה 2 — 3 קטעי קוד
רמה ⭐⭐ — לולאות מקוננות ותנאים
מטרה: 3 דקות לקטע. Symbol Table עם כמה עמודות. תשים לב לפלטים מרובים.
קוד 2.1 — Zenith: משולש כוכביות
// שאלות: א) מה הפלטים? ב) מהו הדפוס הכללי?
FOR i = 1 TO 5
LET line = ""
FOR j = 1 TO i
SET line TO line + "*"
END FOR
PRINT line
END FOR
דפוס: משולש ישר-זווית. שורה i = i כוכביות. לולאה חיצונית = שורות, פנימית = תווים.
קוד 2.2 — Kova: Inversions
// arr = [3,1,4,1,5] שאלות: א) מה total? ב) מה עושה?
var arr[5]:num
arr[0]:=3; arr[1]:=1; arr[2]:=4; arr[3]:=1; arr[4]:=5
var total:num; total:=0
@ i in 0..4 {
@ j in 0..4 {
? arr[i] > arr[j] { total := total + 1 }
}
}
>> total
Dry Run פתרון מלא ›
arr[0]=3: גדול מ-{1,1} → 2. arr[1]=1: → 0. arr[2]=4: גדול מ-{3,1,1} → 3. arr[3]=1: → 0. arr[4]=5: גדול מ-{3,1,4,1} → 4.
total = 2+0+3+0+4 = 9
מה עושה: סופר זוגות (i,j) שarr[i]>arr[j] = מספר Inversions (מדד מיון).
קוד 2.3 — TalonScript: שפה חדשה
══ TalonScript — מפרט מקוצר ══
x <~ expr ; assignment (x = expr)
iter# var [a:b] ; for var = a to b (inclusive!)
?! cond ?> block ; if cond then block
>? cond ?> block ; while cond
say expr ; print
fn f[params] ; function def / ret expr = return
%% = modulo ^^ = power ++ = string concat
>> and << = greater/less
// שאלות: א) מה הפלט? ב) מה עושה?
n <~ 10
sum <~ 0
iter# i [1:n] ?>
?! i %% 2 == 0 ?>
sum <~ sum + i
!?
!iter
say sum
Dry Run פתרון מלא ›
זוגיים מ-1 עד 10: 2+4+6+8+10 = 30
say sum → 30 · מה עושה: סכום המספרים הזוגיים מ-1 עד n.
✏תרגול — רמה 23 שאלות
תרגול 2.1
מה Pattern: a<~0; b<~1; iter# i [1:n]: c<~a++b; a<~b; b<~c?
✓ תשובה: א) Fibonacci — a,b = b, a+b. זה ה-Pattern הקלאסי. לא צריך Dry Run מלא — ניתן לזהות ישירות!
תרגול 2.2
AxonLang: DECL n=4; DECL total=0
EACH i OVER 1->n+1
EACH j OVER 1->i+1
total UPDATE total PLUS 1
END
END
DISPLAY total — מה total?
Kova: x:=5; y:=5; @@ x != y { x:=x-1 }; >> x — מה x?
✓ תשובה: א) 5 — Edge Case! @@ x!=y: 5!=5=FALSE → 0 iterations מיד. x לא השתנה.
📌 סיכום ביניים — לולאות מקוננות
לולאה מקוננת = הפנימית מסתיימת במלואה בכל סיבוב של החיצונית. אם הפנימית קבועה — פשוט n × m. אם היא תלויה ב-i — סוכמים סדרה (n(n+1)/2 או n(n−1)/2), אבל רק אחרי שווידאתם את הגבולות על n = 3.
הטעות שחוזרת: להחיל נוסחה מוכרת על לולאה שהגבול שלה שונה במעט.
// רמה 3 — 3 קטעי קוד
רמה ⭐⭐⭐ — רקורסיה ו-Multi-Function
מטרה: 5 דקות. עץ קריאות + Symbol Table לכל frame. אל תנסה לעקוב "בראש".
קוד 3.1 — Zenith: היפוך מחרוזת רקורסיבי
FUNC head(s)
RETURN s[0]
END FUNC
FUNC tail(s)
RETURN s[1 TO s.SIZE - 1]
END FUNC
FUNC reverse(s)
IF s.SIZE = 0 THEN
RETURN ""
END IF
RETURN reverse(tail(s)) + head(s)
END FUNC
PRINT reverse("Hello")
fn square[x]
ret x * x
endfn
fn sum_squares[n]
total <~ 0
iter# i [1:n] ?>
total <~ total + square[i]
!iter
ret total
endfn
fn is_perfect_square[n]
?! n >> 0 ?>
iter# r [1:n] ?>
?! square[r] == n ?>
ret 1
!?
!iter
!?
ret 0
endfn
say sum_squares[4]
say is_perfect_square[16]
say is_perfect_square[15]
Dry Run פתרון מלא + Call Stack ›
sum_squares[4]: 1+4+9+16 = 30 → say 30
is_perfect_square[16]: r=4: 16==16 → ret 1 → say 1
is_perfect_square[15]: אין r² = 15 → ret 0 → say 0
פלטים: 30, 1, 0
Call Stack בשיא (r=4): Frame 3: square[4] ← פעיל · Frame 2: is_perfect_square[16] · Frame 1: main
קוד 3.3 — Zenith: רקורסיה עם 2 Base Cases
FUNC f(n)
IF n = 0 THEN RETURN 0 END IF
IF n = 1 THEN RETURN 1 END IF
IF n MOD 2 = 0 THEN
RETURN f(n / 2)
END IF
RETURN f(n - 1) + f(n - 2)
END FUNC
PRINT f(7)
PRINT f(8)
TalonScript: fn power[base, exp]
?! exp IS 0 ?> ret 1 !?
?! exp %% 2 IS 0 ?>
half <~ power[base, exp DIV 2]
ret half * half
!?
ret base * power[base, exp MINUS 1]
endfn
say power[3,4] — מה הפלט?
FUNC g(n, acc)
IF n = 0 THEN RETURN acc END IF
RETURN g(n - 1, acc + n)
END FUNC
PRINT g(5, 0) — מה הפלט?
✓ תשובה: א) 15 — Tail Recursion. g(5,0)→g(4,5)→g(3,9)→g(2,12)→g(1,14)→g(0,15)=15. מחשב 5+4+3+2+1.
תרגול 3.3
מה Tail Recursion? מה היתרון שלה?
✓ תשובה: ב) — Tail Recursion = הקריאה הרקורסיבית היא האחרונה. יתרון: TCO = אין Stack Overflow. Python לא מיישם TCO, אבל חשוב לדעת לגאמא.
🎯 דגש למבחן
רקורסיה תחת לחץ: אל תנסו להיות קומפיילר אנושי. אף אחד לא מחזיק בראש ארבע רמות קריאות בו-זמנית — וזה בדיוק המקום שבו נופלים על Off-by-one. במקום זה, קחו עשר שניות וציירו: בשרשרת (קריאה אחת בכל רמה) כתבו שורה-שורה עד תנאי העצירה ואז הציבו חזרה מלמטה למעלה. בקריאה כפולה (fib(n-1) + fib(n-2)) ציירו עץ קריאות קטן, ובקומבינציות ארוכות — טבלה עם עמודה לכל פרמטר. שתי נקודות שמצילות: תמיד לבדוק את תנאי העצירה על הקלט הקטן ביותר (n=0 ו-n=1), ולשים לב אם הפעולה מתבצעת לפני הקריאה הרקורסיבית או אחריה — זה משנה את סדר הפלט לגמרי.
📌 סיכום ביניים — רקורסיה
פונקציה רקורסיבית = תנאי עצירה + צעד שמתקרב אליו. כל קריאה היא Stack Frame עם עותק פרטי של הפרמטרים, ולכן n של רמה אחת לא "נדרס" ברמה שמתחתיה.
אם אחרי דקה אתם לא רואים את התשובה — עברו לציור. זה מהיר יותר מלנחש.
// רמה 4 — כנס-סטייל
רמה ⭐⭐⭐⭐ — כנס-סטייל
מטרה: 7–10 דקות לכל קטע. קרא מפרט → מיפוי → Trace → ענה. שאלות מרובות לכל קטע.
קוד 4.1 — TalonScript: Bubble Sort
// arr = [9,4,7,2,6] 5 שאלות:
// 1) מה הפלט? 2) arr[2] לפני outer loop iter ה-3?
// 3) כמה swaps? 4) שם האלגוריתם? 5) Big-O?
arr[0]<~9; arr[1]<~4; arr[2]<~7; arr[3]<~2; arr[4]<~6
n <~ 5
iter# i [0:n-2] ?>
iter# j [0:n-2-i] ?>
?! arr[j] >> arr[j+1] ?>
tmp <~ arr[j]; arr[j] <~ arr[j+1]; arr[j+1] <~ tmp
!?
!iter
!iter
iter# k [0:n-1] ?>
say arr[k]
!iter
DECL <name> = <val> ; variable
<name> UPDATE <expr> ; assignment
EACH <var> OVER <a>-><b> ; for (EXCLUSIVE upper!)
UNTIL <cond>: ...END ; while
WHEN <cond>: ...END ; if
OTHERWISE: ...END ; else
DISPLAY <expr> ; print
OPERATORS: IS(==) GT(>) LT(<) PLUS MINUS TIMES DIV MOD POWER
// Collatz Sequence — 4 שאלות:
// 1) מה הפלט? 2) ערך n ביציאה? 3) כמה DIV? 4) מה עושה?
DECL n = 360
DECL steps = 0
UNTIL n GT 1:
WHEN n MOD 2 IS 0:
n UPDATE n DIV 2
END
OTHERWISE:
n UPDATE n TIMES 3 PLUS 1
END
steps UPDATE steps PLUS 1
END
DISPLAY n
DISPLAY steps
1) פלט: 1, 19 · 2) n=1 ביציאה · 3) 15 פעמים DIV · 4) Collatz Conjecture! (לא הוכח מתמטית)
קוד 4.3 — Zenith: Binary Search Recursive
// arr=[2,5,7,10,13,18,25,40], 1-based
FUNC bsearch(arr, lo, hi, target)
IF lo > hi THEN RETURN -1 END IF
LET mid = (lo + hi) / 2
IF arr[mid] = target THEN RETURN mid END IF
IF arr[mid] < target THEN
RETURN bsearch(arr, mid + 1, hi, target)
END IF
RETURN bsearch(arr, lo, mid - 1, target)
END FUNC
PRINT bsearch(arr, 1, 8, 7) // שאלה: מה הפלט?
PRINT bsearch(arr, 1, 8, 100) // שאלה: מה הפלט?
AxonLang: DECL a=2; DECL b=3; DECL res=0
EACH i OVER 0->4
WHEN i MOD 2 IS 0:
res UPDATE res PLUS a POWER i
END
OTHERWISE:
res UPDATE res MINUS b
END
END
DISPLAY res — מה הפלט?
fn collatz_len[n]
steps <~ 0
>? n ISNT 1 ?>
?! n %% 2 IS 0 ?>
n <~ n DIV 2
!?
?! n %% 2 ISNT 0 ?>
n <~ n TIMES 3 PLUS 1
!?
steps <~ steps PLUS 1
?,
ret steps
endfn
say collatz_len[10]
say collatz_len[1]מה שני הפלטים? ומה יקרה לn=0?
✓ תשובה: ג) 0 — n=-3 ≤ 0 → RETURN 0. Base Case תופס את המספרים השליליים!
// אתגר מעשי
אתגר מעשי — הרצת קוד מומצא: לולאות
שיא השיעור: לבנות ולתקן מערכות אמיתיות — מפרשים, פרוטוקולים, מכונות. פתרו את החובה ואז את האתגר; ההגשה נבדקת אוטומטית מול מקרי-קצה נסתרים.
T2 · בסיסי250 נק'~12 דק'debug
תיקון באג — טווח לולאה (inclusive)
הפונקציה אמורה לסכם את ריבועי המספרים בטווח [a, b] כולל שני הקצוות. אך היא שבורה: הלולאה אינה כוללת את b (range(a, b) עוצר לפני b), ולכן sum_squares(1, 3) מחזיר 5 במקום 14. מצא ותקן. החזר את הגרסה המתוקנת.
// הקוד השבור לתיקון
def sum_squares(a: int, b: int) -> int:
tot = 0
for i in range(a, b): # באג כאן
tot += i * i
return tot
דוגמאות
sum_squares(1, 3)→14
sum_squares(2, 2)→4
הפתרון נשמר מקומית ומשותף עם עמוד „כתיבת קוד”.
פתרון-ייחוס תיקון באג — טווח לולאה (inclusive) ›
def sum_squares(a: int, b: int) -> int:
tot = 0
for i in range(a, b + 1): # התיקון: b+1 כדי לכלול את b
tot += i * i
return tot
T3 · בינוני400 נק'~30 דק'algorithmic
אינטרפרטר לולאות מקוננות
ממש מפרש לשפה זעירה עם לולאות מקוננות. פקודות (שורה לכל אחת): "SET v n" (קבע v=n) · "ADD v n" · "MUL v n" · "OUT v" (הוסף את v לפלט) · "LOOP k" ... "END" (חזור על הבלוק k פעמים; קינון מותר). משתנה שלא אותחל שווה 0. החזר את רשימת ערכי ה-OUT לפי הסדר. שים לב: LOOP 0 מדלג על הבלוק כולו.
דוגמאות
run_loops(['SET r 1','LOOP 3','MUL r 2','END','OUT r'])→[8]
run_loops(['SET s 0','LOOP 2','LOOP 3','ADD s 1','END','END','OUT s'])→[6]
הפתרון נשמר מקומית ומשותף עם עמוד „כתיבת קוד”.
פתרון-ייחוס אינטרפרטר לולאות מקוננות ›
def run_loops(program: list[str]) -> list:
out = []; V = {}
def find_end(start): # END התואם ל-LOOP (מטפל בקינון)
depth = 0; i = start
while i < len(program):
op = program[i].split()[0]
if op == 'LOOP': depth += 1
elif op == 'END':
if depth == 0: return i
depth -= 1
i += 1
return i
def exec_range(lo, hi):
idx = lo
while idx < hi:
p = program[idx].split(); op = p[0]
if op == 'SET': V[p[1]] = int(p[2]); idx += 1
elif op == 'ADD': V[p[1]] = V.get(p[1], 0) + int(p[2]); idx += 1
elif op == 'MUL': V[p[1]] = V.get(p[1], 0) * int(p[2]); idx += 1
elif op == 'OUT': out.append(V.get(p[1], 0)); idx += 1
elif op == 'LOOP':
k = int(p[1]); body = idx + 1; end = find_end(body)
for _ in range(k): exec_range(body, end)
idx = end + 1 # דילוג נכון גם כש-k==0
else: idx += 1
exec_range(0, len(program))
return out
שאלות תרגול ותשובות (10)
שאלה 1 · מה יודפס?
LET x = 1
LET count = 0
WHILE x < 100
SET x TO x * 3
SET count TO count + 1
END WHILE
PRINT x
PRINT count
א. 81 ו-4
ב. 243 ו-5
ג. 100 ו-5
ד. 243 ו-4
תשובה: ב
x: 1→3→9→27→81→243. הלולאה מסתיימת רק אחרי שהתנאי נשבר, ולכן x=243 ו-count=5.
שאלה 2 · כמה פעמים רץ הגוף הפנימי?
SET c TO 0
LOOP i FROM 1 TO 4
LOOP j FROM i TO 4
ADD c BY 1
ENDLOOP
ENDLOOP
OUTPUT c
א. 16
ב. 10
ג. 6
ד. 12
תשובה: ב
4+3+2+1 = 10 — הפנימית מתחילה ב-i, ולכן מתקצרת בכל סיבוב.
שאלה 3 · מה מחזירה f(5)?
FUNC f(n)
IF n <= 1 THEN
RETURN 1
END IF
RETURN n * f(n - 1)
END FUNC
א. 15
ב. 25
ג. 120
ד. 60
תשובה: ג
עצרת: 5*4*3*2*1 = 120. פורסים עד תנאי העצירה ומציבים בחזרה למעלה.
שאלה 4 · מה מחזירה g(6)?
FUNC g(n)
IF n < 2 THEN
RETURN n
END IF
RETURN g(n - 1) + g(n - 2)
END FUNC
א. 8
ב. 13
ג. 5
ד. 21
תשובה: א
פיבונאצ'י: 0,1,1,2,3,5,8 — g(6)=8. קריאה כפולה מחייבת עץ קריאות ולא שרשרת.
שאלה 5 · איזה אלגוריתם מזוהה כאן?
@ i in 0..|a|-2 {
@ j in 0..|a|-2-i {
? a[j] > a[j+1] {
SWAP a[j] a[j+1]
}
}
}
א. Binary Search
ב. Bubble Sort
ג. Selection Sort
ד. Linear Search
תשובה: ב
השוואה והחלפה של שכנים בלולאה מקוננת — חתימה קלאסית של Bubble Sort.
שאלה 6 · כמה איטרציות יבצע החיפוש על מערך ממוין באורך 64 במקרה הגרוע?
lo := 0
hi := |a| - 1
@@ lo <= hi {
mid := (lo + hi) / 2
? a[mid] == t { return mid }
? a[mid] < t { lo := mid + 1 } ~ { hi := mid - 1 }
}
א. 64
ב. 32
ג. 7
ד. 12
תשובה: ג
חיפוש בינארי: log₂(64)=6 חצאים, ועד 7 בדיקות במקרה הגרוע.
שאלה 7 · מה יודפס? (שימו לב לסדר: ההדפסה אחרי הקריאה הרקורסיבית)
FUNC p(n)
IF n = 0 THEN
RETURN
END IF
p(n - 1)
PRINT n
END FUNC
p(3)
א. 3 2 1
ב. 1 2 3
ג. 3 2 1 0
ד. 1 2 3 בלולאה אינסופית
תשובה: ב
הקריאות יורדות עד 0 ורק בדרך חזרה מדפיסות — ולכן הסדר עולה.
שאלה 8 · מה קורה כשמריצים את הקוד על מערך ריק?
lo := 0
hi := |a| - 1
max := a[0]
@ i in 1..hi {
? a[i] > max { max := a[i] }
}
א. מחזיר 0
ב. מחזיר את המקסימום כרגיל
ג. נופל כבר בשורה של a[0]
ד. נכנס ללולאה אינסופית
תשובה: ג
Edge case קלאסי: אתחול המקסימום מהאיבר הראשון קורס כשאין איברים בכלל.
שאלה 9 · מה יודפס?
LET s = 0
FOR i = 1 TO 5
IF i = 3 THEN
SET i TO 5
END IF
SET s TO s + i
END FOR
PRINT s
א. 15
ב. 13
ג. 12
ד. 8
תשובה: ב
1+2, ואז i הופך ל-5 ומתווסף (8), ובסיבוב האחרון i=5... כלומר 1+2+5+5 = 13.
שאלה 10 · מה מחזירה h(4)?
FUNC h(n)
IF n = 0 THEN
RETURN 0
END IF
RETURN h(n - 1) + n * n
END FUNC
א. 16
ב. 30
ג. 10
ד. 20
תשובה: ב
סכום ריבועים: 1+4+9+16 = 30 — פורסים עד 0 ומציבים בחזרה.