[
 {
  "id": "exam-2023-dec-q1",
  "kind": "exam",
  "title": "Κάντο όπως ο Βιετά",
  "source": {
   "title": "Κατατακτήριες Δεκεμβρίου 2023, Θέμα 1",
   "url": "https://progintro.github.io/exams/2023/progintro-exam-dec-23.pdf",
   "years": [
    2023
   ]
  },
  "chapters": [
   6,
   3,
   4
  ],
  "topics": [
   "floating-point",
   "loops",
   "command-line-args",
   "math-algorithms"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α6.20",
  "path": "questions/exams/exam-2023-dec-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-dec-q1.html",
  "statement": "Ο Γάλλος μαθηματικός Βιετά (François Viète) υπήρξε ο πρώτος μαθηματικός που\nχρησιμοποίησε ευρέως σύμβολα για να εκφράσει αριθμητικές ποσότητες. Το 1593 κατάφερε\nνα εκφράσει και να υπολογίσει τον αριθμό $\\pi$ με ακρίβεια 9 δεκαδικών, βελτιώνοντας\nέτσι το σχετικό αποτέλεσμα του Αρχιμήδη. Για να υπολογίσει το $\\pi$, ο Βιετά\nχρησιμοποίησε μια σχέση που χρησιμοποιεί ένα απειρογινόμενο όρων $, γνωστό ως\nφόρμουλα Βιετά προς τιμήν του:\n\n$$\\frac{2}{\\pi} = \\underbrace{\\frac{\\sqrt{2}}{2}}_{t_1} \\cdot \\underbrace{\\frac{\\sqrt{2+\\sqrt{2}}}{2}}_{t_2} \\cdot \\underbrace{\\frac{\\sqrt{2+\\sqrt{2+\\sqrt{2}}}}{2}}_{t_3} \\cdots$$\n\nΛύνοντας την παραπάνω σχέση ως προς $\\pi$, μπορούμε και εμείς να προσεγγίσουμε το $\\pi$\nόπως ο Βιετά. Μάλιστα, όσους περισσότερους όρους $ χρησιμοποιούμε, τόσο καλύτερη\nη προσέγγισή μας. Γράψτε ένα πρόγραμμα C το οποίο παίρνει έναν θετικό ακέραιο ως\nόρισμα από την γραμμή εντολών που αντιπροσωπεύει πόσους πρώτους όρους $ να\nχρησιμοποιήσει στον υπολογισμό του $\\pi$ και στην συνέχεια εκτυπώνει την προσέγγιση\nτου $\\pi$ με 9 δεκαδικά ψηφία. Παραδείγματα εκτέλεσης είναι τα εξής:\n\n```text\n$ ./vieta 2\nMultiplied first 2 ti terms, pi = 3.061467459\n$ ./vieta 5\nMultiplied first 5 ti terms, pi = 3.140331157\n$ ./vieta 50\nMultiplied first 50 ti terms, pi = 3.141592654\n```",
  "hint": "Παρατηρήστε ότι ο αριθμητής κάθε όρου προκύπτει από τον αριθμητή του προηγούμενου:\nαν  = \\sqrt{2}$, τότε {i+1} = \\sqrt{2 + a_i}$. Κρατήστε λοιπόν σε έναν βρόχο\nτον τρέχοντα αριθμητή και το γινόμενο σε μεταβλητές `double` (με τη `sqrt` του\n`<math.h>`, μεταγλώττιση με `-lm`) και στο τέλος λύστε ως προς $\\pi$. Μετατρέψτε το\n`argv[1]` σε ακέραιο και ελέγξτε ότι δόθηκε και είναι θετικός."
 },
 {
  "id": "exam-2023-dec-q2",
  "kind": "exam",
  "title": "Εαυτοί Αριθμοί",
  "source": {
   "title": "Κατατακτήριες Δεκεμβρίου 2023, Θέμα 2",
   "url": "https://progintro.github.io/exams/2023/progintro-exam-dec-23.pdf",
   "years": [
    2023
   ]
  },
  "chapters": [
   16,
   4
  ],
  "topics": [
   "math-algorithms",
   "loops",
   "command-line-args"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α16.19",
  "path": "questions/exams/exam-2023-dec-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-dec-q2.html",
  "statement": "Στην θεωρία αριθμών, ένας φυσικός αριθμός $ λέγεται *εαυτός* (self) όταν δεν\nυπάρχει κάποιος φυσικός αριθμός $, έτσι ώστε το $ να ισούται με το άθροισμα του\n$ και των ψηφίων του $ (με βάση το 10 σε αυτό το θέμα). Έστω (n)$ η συνάρτηση\nπου υπολογίζει το άθροισμα ενός φυσικού $ και των ψηφίων του. Τότε ένας αριθμός $\nείναι εαυτός αν και μόνο αν $\\nexists m. F(m) = n$. Για παράδειγμα,\n(15) = 15 + 1 + 5 = 21$ και επομένως ο αριθμός 21 δεν είναι εαυτός. Αντίθετα, ο\nαριθμός 20 είναι εαυτός καθώς δεν υπάρχει φυσικός αριθμός $ έτσι ώστε (m) = 20$.\nΥπάρχουν μόλις 13 εαυτοί αριθμοί μικρότεροι του 100:\n\n$$1, 3, 5, 7, 9, 20, 31, 42, 53, 64, 75, 86, 97$$\n\nΓράψτε ένα πρόγραμμα C το οποίο βρίσκει και τυπώνει όλους τους εαυτούς αριθμούς σε\nένα εύρος φυσικών αριθμών 0$ (το εύρος είναι κλειστό, δηλαδή τα άκρα\nσυμπεριλαμβάνονται), όπου οι αριθμοί δίνονται από την γραμμή εντολών. Ακολουθεί\nπαράδειγμα εκτέλεσης για να βρούμε όλους τους εαυτούς αριθμούς στο διάστημα\n10000$:\n\n```text\n$ ./self 9900 10000\nSelf numbers: 9903 9914 9925 9927 9938 9949 9960 9971 9982 9993\nFound 10 total\n```",
  "hint": "Γράψτε πρώτα μια συνάρτηση για το (m)$, με `% 10` και `/ 10` σε βρόχο. Για\nκάθε $ του εύρους δεν χρειάζεται να δοκιμάσετε όλα τα $: αφού (m) \\ge m$ και\nτο άθροισμα ψηφίων ενός αριθμού είναι μικρό (το πολύ 9 ανά ψηφίο), αρκεί να\nελέγξετε λίγα $ ακριβώς κάτω από το $. Προσέξτε ότι τα όρια δίνονται ως\nσυμβολοσειρές στο `argv` και ότι πρέπει να μετρήσετε πόσοι βρέθηκαν."
 },
 {
  "id": "exam-2023-dec-q3",
  "kind": "exam",
  "title": "Σκαλί-Σκαλί",
  "source": {
   "title": "Κατατακτήριες Δεκεμβρίου 2023, Θέμα 3",
   "url": "https://progintro.github.io/exams/2023/progintro-exam-dec-23.pdf",
   "years": [
    2023
   ]
  },
  "chapters": [
   25,
   16,
   11
  ],
  "topics": [
   "dynamic-programming",
   "recursion",
   "complexity",
   "integer-representation"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α25.5",
  "path": "questions/exams/exam-2023-dec-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-dec-q3.html",
  "statement": "Ένα παιδί ανεβαίνει μια σκάλα και σε κάθε βήμα του ανεβαίνει 1, 2 ή 3 σκαλιά. Έστω\nότι η σκάλα έχει 5 σκαλιά. Ένας τρόπος να τα ανέβει είναι 1-1-1-1-1, δηλαδή ένα σκαλί\nτην φορά. Ένας άλλος είναι ο 2-2-1 (δύο σκαλιά στα πρώτα δύο βήματα και μετά ένα\nσκαλί). Άλλοι πιθανοί τρόποι είναι οι 3-2, 2-3, 3-1-1, κ.ο.κ - σε κάθε περίπτωση ο\nσυνολικός αριθμός των σκαλιών που ανέβηκε πρέπει να ισούται με τον αριθμό των σκαλιών\nτης σκάλας. Γράψτε ένα πρόγραμμα C το οποίο διαβάζει τον συνολικό αριθμό των\nσκαλοπατιών και επιστρέφει τον αριθμό των διαφορετικών τρόπων με τους οποίους το\nπαιδί μπορεί να ανέβει την σκάλα. Το πρόγραμμά σας θέλουμε να βγάζει σωστά\nαποτελέσματα για σκάλες μέχρι 50 σκαλιά. Λάβετε υπόψη σας ότι στην C δεν μπορούν να\nαναπαρασταθούν ακέραιοι μεγαλύτεροι από το ^{64}-1$, δεδομένου ότι ο ευρύτερος\nτύπος ακεραίου που μπορούμε να έχουμε είναι ο `unsigned long long` (των 8 bytes). Ο\nαλγόριθμός σας πρέπει να έχει χρονική πολυπλοκότητα γρηγορότερη από (n^2)$, όπου\n$ ο αριθμός των σκαλιών. Ακολουθούν ενδεικτικές εκτελέσεις:\n\n```text\n$ ./step\nPlease provide the number of steps: 4\nThere are 7 different ways to climb the ladder\n$ ./step\nPlease provide the number of steps: 5\nThere are 13 different ways to climb the ladder\n$ ./step\nPlease provide the number of steps: 6\nThere are 24 different ways to climb the ladder\n$ ./step\nPlease provide the number of steps: 50\nThere are 10562230626642 different ways to climb the ladder\n```",
  "hint": "Σκεφτείτε το τελευταίο βήμα του παιδιού: ήταν 1, 2 ή 3 σκαλιά, οπότε οι τρόποι για\n$ σκαλιά εκφράζονται μέσω των τρόπων για λιγότερα σκαλιά. Η απλή αναδρομή\nεπαναϋπολογίζει τα ίδια υποπροβλήματα εκθετικά πολλές φορές· υπολογίστε τις τιμές από\nκάτω προς τα πάνω (ή απομνημονεύστε τις) ώστε να πετύχετε (n)$. Προσέξτε τις\nαρχικές περιπτώσεις και χρησιμοποιήστε `unsigned long long` με `%llu`."
 },
 {
  "id": "exam-2023-dec-q4",
  "kind": "exam",
  "title": "Το Νερό Νεράκι",
  "source": {
   "title": "Κατατακτήριες Δεκεμβρίου 2023, Θέμα 4",
   "url": "https://progintro.github.io/exams/2023/progintro-exam-dec-23.pdf",
   "years": [
    2023
   ]
  },
  "chapters": [
   25,
   15,
   13
  ],
  "topics": [
   "arrays",
   "complexity",
   "dynamic-memory",
   "problem-solving"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α25.9",
  "path": "questions/exams/exam-2023-dec-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-dec-q4.html",
  "statement": "Το νερό είναι πολύτιμο και είναι σημαντικό να γνωρίζουμε ποια είναι τα διαθέσιμα\nαποθέματά μας. Δοθέντος του υψομετρικού χάρτη μιας περιοχής, θέλουμε να μπορούμε να\nυπολογίζουμε την μέγιστη ποσότητα νερού της βροχής που μπορεί να διατηρηθεί μέσα στις\nφυσικές δεξαμενές που σχηματίζονται από την διαμόρφωση του εδάφους. Για απλοποίηση,\nθεωρούμε ότι ο υψομετρικός χάρτης είναι μονοδιάστατος και μας δίνεται ως μια σειρά\nθετικών ακεραίων (μονάδες ύψους με πλάτος 1) και η ποσότητα νερού μετριέται επίσης\nστις ίδιες μονάδες ύψους. Το Σχήμα 1 δείχνει ένα παράδειγμα.\n\n| Θέση | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| Γη (ύψος) | 0 | 1 | 0 | 2 | 1 | 0 | 1 | 3 | 2 | 1 | 2 | 1 |\n| Νερό | 0 | 0 | 1 | 0 | 1 | 2 | 1 | 0 | 0 | 1 | 0 | 0 |\n\n*Σχήμα 1: Οπτικοποίηση της ποσότητας νερού που θα \"παγιδευτεί\" μετά την βροχή για\nέναν ενδεικτικό υψομετρικό χάρτη. Στο παράδειγμα, μέχρι 6 μονάδες νερού μπορούν να\nσυγκρατηθούν από αυτόν τον χάρτη (1 μονάδα στην 3η θέση, 1 στην 5η θέση, 2 στην 6η\nθέση, 1 στην 7η θέση και 1 στην 10η θέση).*\n\n> Σημείωση: στο πρωτότυπο το Σχήμα 1 είναι ραβδόγραμμα (καφέ η γη, μπλε το νερό)·\n> εδώ δίνεται ως πίνακας με τα ίδια δεδομένα.\n\nΓράψτε ένα πρόγραμμα C που διαβάζει τον πίνακα των υψών του υψομετρικού χάρτη και\nεπιστρέφει την μέγιστη ποσότητα του νερού της βροχής που μπορεί να συγκρατηθεί από\nαυτόν. Το πρόγραμμά σας πρέπει να έχει χρονική πολυπλοκότητα καλύτερη από (n^2)$,\nόπου $ ο αριθμός των δοθέντων υψών και την ελάχιστη δυνατή χρήση μνήμης. Αφού\nγράψετε το πρόγραμμά σας, καταγράψτε και εξηγήστε την πολυπλοκότητά του ως προς τον\nχρόνο και τον χώρο μνήμης που απαιτεί. Ακολουθούν ενδεικτικές εκτελέσεις:\n\n```text\n$ ./water\nProvide the number of heights: 12\nProvide the heights: 0 1 0 2 1 0 1 3 2 1 2 1\nUp to 6 units of water can be trapped\n$ ./water\nProvide the number of heights: 12\nProvide the heights: 4 1 0 2 1 0 1 3 2 3 2 1\nUp to 14 units of water can be trapped\n./water\nProvide the number of heights: 20\nProvide the heights: 0 2 3 1 4 4 4 4 3 8 9 3 9 0 6 4 6 0 9 5\nUp to 38 units of water can be trapped\n```",
  "hint": "Το νερό πάνω από τη θέση $ ορίζεται από το μικρότερο από τα δύο ψηλότερα «τοιχώματα»\nαριστερά και δεξιά της, μείον το ύψος της θέσης. Με δύο προ-υπολογισμένους πίνακες\nμεγίστων παίρνετε (n)$ χρόνο αλλά (n)$ επιπλέον μνήμη· για ελάχιστη μνήμη\nσκεφτείτε δύο δείκτες που κινούνται από τα άκρα προς το κέντρο κρατώντας μόνο τα\nτρέχοντα μέγιστα. Δεσμεύστε τον πίνακα των υψών δυναμικά αφού διαβάσετε το $."
 },
 {
  "id": "exam-2023-fall-ex0-q1",
  "kind": "exam",
  "title": "Ραβασάκι",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #0 (Valentine's Themed), Θέμα 1",
   "url": "https://progintro.github.io/exams/2023/fall/ex0/",
   "years": [
    2023
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α9.18",
  "path": "questions/exams/exam-2023-fall-ex0-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex0-q1.html",
  "statement": "Πρόγραμμα: `ravasaki.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα που διαβάζει το κείμενο που δίνεται από την πρότυπη είσοδο (stdin) και το τυπώνει στην πρότυπη έξοδο (stdout) προσθέτοντας μια κόκκινη καρδιά στο τέλος κάθε γραμμής. Παράδειγμα εκτέλεσης:\n\n```text\n$ cat maravegias.txt\nΚαι τυχαίο και γραφτό,\nτο μεγάλο μωρό που παίζει με τόξο και βέλη\nπου χτυπάει και φεύγει όλα τα ανατρέπει,\nμα ο χάρτης τον δρόμο σου δείχνει\nΤου κρυμμένου θησαυρού το ταξίδι τελειώνει,\nεκεί που είναι αδύνατο να ‘μαστε μόνοι\nΣε κοιτάζω στα μάτια σαν καθρέφτες γυαλίζουν,\nτον πιο ωραίο εαυτό μας αντικατοπτρίζουν\n$ gcc -o ravasaki ravasaki.c\n$ ./ravasaki < maravegias.txt\nΚαι τυχαίο και γραφτό, <3\nτο μεγάλο μωρό που παίζει με τόξο και βέλη <3\nπου χτυπάει και φεύγει όλα τα ανατρέπει, <3\nμα ο χάρτης τον δρόμο σου δείχνει <3\nΤου κρυμμένου θησαυρού το ταξίδι τελειώνει, <3\nεκεί που είναι αδύνατο να ‘μαστε μόνοι <3\nΣε κοιτάζω στα μάτια σαν καθρέφτες γυαλίζουν, <3\nτον πιο ωραίο εαυτό μας αντικατοπτρίζουν <3\n```\n\n> Σημείωση: στο πρωτότυπο το παράδειγμα είναι στιγμιότυπο τερματικού ([εικόνα](https://progintro.github.io/exams/2023/fall/ex0/images/ravasaki.png)), όπου το ` <3` στο τέλος κάθε γραμμής εμφανίζεται με κόκκινο χρώμα.",
  "hint": "Διαβάστε χαρακτήρα προς χαρακτήρα με `getchar` μέχρι το `EOF`: όταν συναντάτε `'\\n'`, τυπώστε πρώτα την καρδιά και μετά την αλλαγή γραμμής. Για το κόκκινο χρώμα ψάξτε τις ANSI escape sequences του τερματικού (και θυμηθείτε να επαναφέρετε το χρώμα). Σκεφτείτε τι γίνεται αν η τελευταία γραμμή δεν τελειώνει σε `'\\n'`."
 },
 {
  "id": "exam-2023-fall-ex0-q2",
  "kind": "exam",
  "title": "Ταιριαστές Καρδιές",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #0 (Valentine's Themed), Θέμα 2",
   "url": "https://progintro.github.io/exams/2023/fall/ex0/",
   "years": [
    2023
   ]
  },
  "chapters": [
   14,
   12
  ],
  "topics": [
   "strings",
   "command-line-args"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α14.13",
  "path": "questions/exams/exam-2023-fall-ex0-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex0-q2.html",
  "statement": "Πρόγραμμα: `hearts.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα που για κάθε όρισμα από την γραμμή εντολών ελέγχει αν η συμβολοακολουθία του ορίσματος περιέχει μόνο *ταιριαστές* καρδιές. Οι ταιριαστές καρδιές ορίζονται ως εξής:\n\n1. Μπορούν να περιέχουν μόνο χαρακτήρες '<' και '3'.\n1. Κάθε καρδιά που κλείνει ('3') πρέπει πρώτα να έχει ανοίξει ('<').\n1. Όλες οι καρδιές που άνοιξαν κλείνουν.\n\nΠαράδειγμα εκτέλεσης:\n\n```text\n$ gcc -o hearts hearts.c\n$ ./hearts '<3' '<.3>' '<<33' '<<<3' '<333' '<<33<3<<<<3<<33333'\n<3: yes\n<.3>: no\n<<33: yes\n<<<3: no\n<333: no\n<<33<3<<<<3<<33333: yes\n```",
  "hint": "Είναι το κλασικό πρόβλημα των ισορροπημένων παρενθέσεων: αρκεί ένας μετρητής «ανοιχτών» καρδιών που ανεβαίνει με `'<'` και κατεβαίνει με `'3'`. Ποιες δύο συνθήκες πρέπει να ελέγξετε, μία κατά τη διάρκεια της σάρωσης και μία στο τέλος; Μην ξεχάσετε τους άκυρους χαρακτήρες."
 },
 {
  "id": "exam-2023-fall-ex0-q3",
  "kind": "exam",
  "title": "Καλύτερο Ταίριασμα",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #0 (Valentine's Themed), Θέμα 3",
   "url": "https://progintro.github.io/exams/2023/fall/ex0/",
   "years": [
    2023
   ]
  },
  "chapters": [
   18,
   19,
   13
  ],
  "topics": [
   "sorting",
   "files",
   "structs",
   "dynamic-memory"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α18.20",
  "path": "questions/exams/exam-2023-fall-ex0-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex0-q3.html",
  "statement": "Πρόγραμμα: `bestmatch.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα που διαβάζει ένα σύνολο από ονόματα ακολουθούμενα από έναν αριθμό που δηλώνει πόσο καλά μας ταιριάζει αυτό το άτομο και τυπώνει τα ονόματα από το μεγαλύτερο στο μικρότερο ταξινομημένα. Τα δεδομένα περιέχονται σε αρχείο που δίνεται ως πρώτο όρισμα. Το αρχείο θα περιέχει κάθε όνομα σε μια γραμμή της μορφής \"όνομα,σκορ\". Ένα παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ cat names.txt\nAlex,3.4\nCasey,9.1\nJordan,2\nTaylor,5.3\nMorgan,1.7\nRiley Avery,6.16\nJamie,0\nQuinn,-1.1\nSkyler,5.88\n$ gcc -o bestmatch bestmatch.c\n$ ./bestmatch names.txt\nCasey,9.1\nRiley Avery,6.16\nSkyler,5.88\nTaylor,5.3\nAlex,3.4\nJordan,2\nMorgan,1.7\nJamie,0\nQuinn,-1.1\n```",
  "hint": "Κρατήστε κάθε εγγραφή σε ένα `struct` (όνομα, σκορ) μέσα σε πίνακα που μεγαλώνει δυναμικά, αφού δεν ξέρετε πόσες γραμμές έχει το αρχείο, και ταξινομήστε με `qsort` και δική σας συνάρτηση σύγκρισης σε φθίνουσα σειρά. Τα ονόματα μπορεί να έχουν κενά, οπότε χωρίστε στο κόμμα. Το σκορ τυπώνεται όπως γράφτηκε (`2`, `6.16`), άρα ίσως σας βολεύει να κρατήσετε και το αρχικό κείμενο. Ελέγξτε το πλήθος των ορισμάτων, αν άνοιξε το αρχείο και τις κακοσχηματισμένες γραμμές."
 },
 {
  "id": "exam-2023-fall-ex0-q4",
  "kind": "exam",
  "title": "Αγαπήσιμοι Αριθμοί",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #0 (Valentine's Themed), Θέμα 4",
   "url": "https://progintro.github.io/exams/2023/fall/ex0/",
   "years": [
    2023
   ]
  },
  "chapters": [
   16,
   2
  ],
  "topics": [
   "math-algorithms",
   "integer-representation",
   "complexity"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α16.20",
  "path": "questions/exams/exam-2023-fall-ex0-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex0-q4.html",
  "statement": "Πρόγραμμα: `lovable.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα που διαβάζει ένα εύρος αριθμών από την κονσόλα (το εύρος είναι κλειστό, δηλαδή περιέχει τα όρια) και τυπώνει όλους τους αγαπήσιμους (lovable) αριθμούς. Ένας αριθμός είναι lovable αν είναι τέλειος κύβος (δηλαδή ένας άλλος ακέραιος υψωμένος στην 3η δύναμη) και ταυτόχρονα παλινδρομικός (δηλαδή διαβάζεται το ίδιο από αριστερά προς τα δεξιά και από δεξιά προς τα αριστερά). Ένα παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ gcc -o lovable lovable.c -lm\n$ ./lovable 100000 100000000\n1030301\n1367631\n```\n\nΟ 1030301 είναι lovable καθώς είναι παλινδρομικός και ταυτόχρονα τέλειος κύβος (= 101^3). Το πρόγραμμά σας πρέπει να βγάζει σωστά αποτελέσματα για όρια μέχρι 10^18.",
  "hint": "Μέχρι το 10^18 δεν μπορείτε να ελέγξετε κάθε αριθμό: απαριθμήστε αντί γι' αυτό τους κύβους `i*i*i`, που είναι μόνο περίπου ένα εκατομμύριο, και ελέγξτε αν είναι παλινδρομικοί αντιστρέφοντας τα ψηφία τους. Χρησιμοποιήστε 64-bit ακέραιους (`long long` / `unsigned long long`) και προσέξτε την ακρίβεια αν υπολογίσετε την κυβική ρίζα του κάτω ορίου με `cbrt`."
 },
 {
  "id": "exam-2023-fall-ex1-q1",
  "kind": "exam",
  "title": "Δεκαεξαδικοί",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #1 (Coreutils Themed), Θέμα 1",
   "url": "https://progintro.github.io/exams/2023/fall/ex1/",
   "years": [
    2023
   ]
  },
  "chapters": [
   9,
   2
  ],
  "topics": [
   "input-output",
   "computers"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α9.19",
  "path": "questions/exams/exam-2023-fall-ex1-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex1-q1.html",
  "statement": "Πρόγραμμα: `hex.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα που διαβάζει το κείμενο που δίνεται από την πρότυπη είσοδο (stdin) και τυπώνει τον κάθε χαρακτήρα στην πρότυπη έξοδο (stdout) σε δεκαεξαδική μορφή χωρίζοντάς το σε γραμμές. Σε κάθε γραμμή πρέπει να τυπώνονται μέχρι 16 χαρακτήρες σε δεκαεξαδική μορφή και πρέπει να υπάρχει ένας κενός χαρακτήρας (' ') ανάμεσα σε κάθε χαρακτήρα στην ίδια γραμμή. Παράδειγμα εκτέλεσης:\n\n```text\n$ cat domo.txt\nどうもありがと Mr. Roboto�\nYou're wondering who I am (secret, secret, I've got a secret)\nMachine or mannequin? (Secret, secret, I've got a secret)\n$ gcc -o hex hex.c\n$ ./hex < domo.txt\n e3 81 a9 e3 81 86 e3 82 82 e3 81 82 e3 82 8a e3\n 81 8c e3 81 a8 20 4d 72 2e 20 52 6f 62 6f 74 6f\n ff 0a 59 6f 75 27 72 65 20 77 6f 6e 64 65 72 69\n 6e 67 20 77 68 6f 20 49 20 61 6d 20 28 73 65 63\n 72 65 74 2c 20 73 65 63 72 65 74 2c 20 49 27 76\n 65 20 67 6f 74 20 61 20 73 65 63 72 65 74 29 0a\n 4d 61 63 68 69 6e 65 20 6f 72 20 6d 61 6e 6e 65\n 71 75 69 6e 3f 20 28 53 65 63 72 65 74 2c 20 73\n 65 63 72 65 74 2c 20 49 27 76 65 20 67 6f 74 20\n 61 20 73 65 63 72 65 74 29 0a\n```\n\nΤο αρχείο εισόδου: [domo.txt](https://progintro.github.io/exams/2023/fall/ex1/domo.txt).",
  "hint": "Διαβάστε byte προς byte με `getchar` και τυπώστε το καθένα με `printf` και την κατάλληλη μορφή για δύο δεκαεξαδικά ψηφία. Ένας μετρητής σάς λέει πότε συμπληρώθηκαν 16 και χρειάζεται αλλαγή γραμμής· προσέξτε στο παράδειγμα πού ακριβώς μπαίνουν τα κενά και τι γίνεται με την τελευταία, ημιτελή γραμμή. Το byte `ff` δείχνει ότι η είσοδος δεν είναι απαραίτητα έγκυρο κείμενο."
 },
 {
  "id": "exam-2023-fall-ex1-q2",
  "kind": "exam",
  "title": "Εντοπισμός Διπλών Ορισμάτων",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #1 (Coreutils Themed), Θέμα 2",
   "url": "https://progintro.github.io/exams/2023/fall/ex1/",
   "years": [
    2023
   ]
  },
  "chapters": [
   14,
   12
  ],
  "topics": [
   "strings",
   "command-line-args"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α14.14",
  "path": "questions/exams/exam-2023-fall-ex1-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex1-q2.html",
  "statement": "Πρόγραμμα: `duplicate.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα που για κάθε όρισμα από την γραμμή εντολών που επαναλαμβάνεται δύο ή περισσότερες φορές τυπώνεται ως πολλαπλό (\"dup\") μία φορά στην πρότυπη έξοδο (stdout). Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ gcc -o duplicate duplicate.c\n$ ./duplicate foo bar foo baz bank zonk bazinga foo zonk\ndup: foo\ndup: zonk\n```",
  "hint": "Συγκρίνετε τα ορίσματα ανά δύο με `strcmp`. Το δύσκολο σημείο είναι το «μία φορά»: το `foo` εμφανίζεται τρεις φορές αλλά τυπώνεται μόνο μία. Ένας τρόπος είναι να αποφασίζετε για κάθε όρισμα μόνο στην πρώτη του εμφάνιση· άλλος είναι να ταξινομήσετε πρώτα, αλλά τότε σκεφτείτε αν αλλάζει η σειρά εξόδου."
 },
 {
  "id": "exam-2023-fall-ex1-q3",
  "kind": "exam",
  "title": "Περιστροφή Πίνακα",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #1 (Coreutils Themed), Θέμα 3",
   "url": "https://progintro.github.io/exams/2023/fall/ex1/",
   "years": [
    2023
   ]
  },
  "chapters": [
   12,
   18,
   13
  ],
  "topics": [
   "multidim-arrays",
   "files",
   "dynamic-memory"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α12.16",
  "path": "questions/exams/exam-2023-fall-ex1-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex1-q3.html",
  "statement": "Πρόγραμμα: `rotate.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα που διαβάζει ένα πίνακα ακεραίων και τον περιστρέφει αντίστροφα από την φορά των δεικτών του ρολογιού. Τα δεδομένα περιέχονται σε αρχείο που δίνεται ως πρώτο όρισμα. Το αρχείο θα περιέχει τον αριθμό των γραμμών και τις στηλών του πίνακα και θα ακολουθούν τα στοιχεία του πίνακα. Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ cat array.txt\n3 5\n2 9 8 3 2\n2 8 1 0 8\n7 1 2 4 3\n$ gcc -o rotate rotate.c\n$ ./rotate array.txt\n2 8 3\n3 0 4\n8 1 2\n9 8 1\n2 2 7\n```",
  "hint": "Διαβάστε τις διαστάσεις με `fscanf` και δεσμεύστε δυναμικά χώρο για `R*C` ακεραίους. Ο περιστραμμένος πίνακας έχει `C` γραμμές και `R` στήλες: βρείτε, από το παράδειγμα, ποιο στοιχείο του αρχικού πίνακα καταλήγει στη γραμμή `i`, στήλη `j` της εξόδου, και τυπώστε με αυτή τη σειρά χωρίς να φτιάξετε δεύτερο πίνακα. Ελέγξτε αρνητικές ή μηδενικές διαστάσεις και αρχεία με λιγότερα στοιχεία από όσα δηλώνουν."
 },
 {
  "id": "exam-2023-fall-ex1-q4",
  "kind": "exam",
  "title": "Debugging",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #1 (Coreutils Themed), Θέμα 4",
   "url": "https://progintro.github.io/exams/2023/fall/ex1/",
   "years": [
    2023
   ]
  },
  "chapters": [
   13,
   21
  ],
  "topics": [
   "dynamic-memory",
   "memory-model",
   "linked-lists",
   "debugging"
  ],
  "difficulty": 2,
  "type": "debug",
  "label": "Α13.10",
  "path": "questions/exams/exam-2023-fall-ex1-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex1-q4.html",
  "statement": "Πρόγραμμα: `broken.c` (25 μονάδες)\n\nΤο πρόγραμμα [broken.c](https://progintro.github.io/exams/2023/fall/ex1/broken.c) δεν λειτουργεί για κάποιον λόγο - όταν το τρέχουμε κρασάρει. Βρείτε όποιο σφάλμα υπάρχει και διορθώστε το χωρίς να εισάγετε καινούρια σφάλματα στο πρόγραμμα. Παράδειγμα επιτυχούς εκτέλεσης ακολουθεί:\n\n```text\n$ gcc -o broken broken.c\n$ ./broken\nyesss! -> yee -> bruh -> NULL\nlistdelete: 1\nyesss! -> yee -> NULL\n```\n\nΤο πρόγραμμα:\n\n```c\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\ntypedef struct node {\n    char value[128];\n    struct node * next;\n} Elem;\n\nint listdelete(char value[], Elem ** head) {\n    Elem * tmp;\n\n    while (*head && strcmp((*head)->value, value)) {\n        head = &((*head)->next);\n    }\n\n    if (*head) {\n        tmp=*head;\n        *head = tmp->next;\n        free(tmp);\n        return 1;\n    }\n    return -1;\n}\n\nint listadd(char value[], Elem ** head) {\n    Elem * new = malloc(sizeof(Elem));\n    if (new == NULL) {\n        return 0;\n    }\n    Elem * tmp;\n    tmp=*head;\n    *head=new;\n    new->next=tmp;\n    strncpy(new->value, value, 127);\n    return 1;\n}\n\nvoid listprint(Elem * list) {\n  while(list) {\n    printf(\"%s -> \", list->value);\n    list = list->next;\n  }\n  printf(\"NULL\\n\");\n}\n\nint main() {\n\n    Elem elem1 = {\"bruh\", NULL};\n    Elem * head = &elem1;\n\n    listadd(\"yee\", &head);\n    listadd(\"yesss!\", &head);\n    listprint(head);\n    printf(\"listdelete: %d\\n\", listdelete(\"bruh\", &head));\n    listprint(head);\n    return 0;\n}\n```",
  "hint": "Εκτελέστε το με `valgrind` ή `gcc -fsanitize=address` και δείτε σε ποια γραμμή σκάει. Αναρωτηθείτε για κάθε κόμβο της λίστας πού ζει στη μνήμη (στοίβα ή σωρός) και ποιοι κόμβοι επιτρέπεται να δοθούν στην `free`. Η διόρθωση πρέπει να κρατήσει τη λίστα συνεπή και να μην αφήνει διαρροές."
 },
 {
  "id": "exam-2023-fall-ex10-q1",
  "kind": "exam",
  "title": "Αφαίρεση Μη Λατινικών Χαρακτήρων",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #10, Θέμα 1",
   "url": "https://progintro.github.io/exams/2023/fall/ex10/",
   "years": [
    2023
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α9.26",
  "path": "questions/exams/exam-2023-fall-ex10-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex10-q1.html",
  "statement": "Πρόγραμμα: `bold.c`\n\nΓράψτε ένα πρόγραμμα το οποίο διαβάζει κείμενο από την πρότυπη είσοδο (stdin) και το τυπώνει στην πρότυπη έξοδο (stdout) με τους εξής περιορισμούς:\n1. Οι αλλαγές γραμμής πρέπει να διατηρούνται.\n1. Πρέπει να μετατρέψει κάθε μη λατινικό χαρακτήρα (A-Za-z) σε κενό (space) χαρακτήρα ' '.\n1. Η πρώτη λέξη σε κάθε γραμμή θέλουμε να φαίνεται **bold**.\n\nΠαράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ gcc -o bold bold.c\n$ cat island.txt\nFifteen men on the Dead Man's Chest Yo-ho-ho,\nand a bottle of rum!\nDrink and the devil had done for the rest Yo-ho-ho,\nand a bottle of rum!\n$ ./bold < island.txt\nFifteen men on the Dead Man s Chest Yo ho ho\nand a bottle of rum\nDrink and the devil had done for the rest Yo ho ho\nand a bottle of rum\n```\n\n> Σημείωση: στο πρωτότυπο το παράδειγμα δίνεται ως στιγμιότυπο τερματικού ([bold.png](https://progintro.github.io/exams/2023/fall/ex10/images/bold.png)) και εδώ μεταγράφεται ως κείμενο: στην έξοδο οι λέξεις Fifteen, and, Drink, and (η πρώτη κάθε γραμμής) εμφανίζονται με έντονα γράμματα.",
  "hint": "Διαβάστε με `getchar` και κρατήστε μια κατάσταση: αν βρίσκεστε ακόμη στην πρώτη λέξη της γραμμής. Μη λατινικοί χαρακτήρες (εκτός από το `'\\n'`) γίνονται κενά και η αλλαγή γραμμής μηδενίζει την κατάσταση. Το «έντονο» (και αντίστοιχα το πλάγιο ή το αναβόσβημα) στο τερματικό γίνεται με ακολουθίες διαφυγής ANSI (ANSI escape codes) που τυπώνετε πριν και μετά το κείμενο, π.χ. `\\033[...m`· ψάξτε ποιος κωδικός αντιστοιχεί στο εφέ που θέλετε και ποιος τα επαναφέρει."
 },
 {
  "id": "exam-2023-fall-ex10-q2",
  "kind": "exam",
  "title": "Ασημένιο Κλάσμα",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #10, Θέμα 2",
   "url": "https://progintro.github.io/exams/2023/fall/ex10/",
   "years": [
    2023
   ]
  },
  "chapters": [
   6,
   3,
   4
  ],
  "topics": [
   "floating-point",
   "loops",
   "math-algorithms"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α6.21",
  "path": "questions/exams/exam-2023-fall-ex10-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex10-q2.html",
  "statement": "Πρόγραμμα: `silver.c`\n\nΈνας τρόπος να προσεγγίσουμε την τιμή του $\\sqrt{2}$ είναι μέσω της παράστασης:\n\n$$ 1 + \\sqrt{2} = 2 + \\frac{1}{2 + \\frac{1}{2 + \\frac{1}{2 + \\cdots}}} $$\n\nΌπου η προσθήκη του κάθε όρου $\\frac{1}{2 + \\cdots}$ βελτιώνει την προσέγγιση. Γράψτε ένα πρόγραμμα το οποίο παίρνει ως όρισμα έναν θετικό ακέραιο που αναπαριστά τον αριθμό των όρων $\\frac{1}{2 + \\cdots}$ που θέλουμε να χρησιμοποιηθούν και τυπώνει την προσέγγιση του $\\sqrt{2}$ με 20 δεκαδικά ψηφία ακριβείας. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ ./silver 1\nsqrt(2) = 1.00000000000000000000\n$ ./silver 2\nsqrt(2) = 1.50000000000000000000\n$ ./silver 3\nsqrt(2) = 1.39999999999999991118\n$ ./silver 4\nsqrt(2) = 1.41666666666666651864\n$ ./silver 5\nsqrt(2) = 1.41379310344827580082\n$ ./silver 1000\nsqrt(2) = 1.41421356237309492343\n```\n\nΓια έναν όρο η δεξιά παράσταση είναι (2 + 0) -> sqrt(2) = 1, για 2 όρους η δεξιά παράσταση είναι (2 + 1 / 2) -> sqrt(2) = 1.5, κοκ.",
  "hint": "Το συνεχές κλάσμα υπολογίζεται εύκολα από μέσα προς τα έξω: ξεκινήστε από τον πιο εσωτερικό όρο και επαναλάβετε με έναν βρόχο. Προσέξτε πώς μετράνε οι όροι στα παραδείγματα (1 όρος δίνει 1) και ότι η παράσταση δίνει 1 + √2, όχι √2. Ελέγξτε ότι το όρισμα είναι θετικός ακέραιος."
 },
 {
  "id": "exam-2023-fall-ex10-q3",
  "kind": "exam",
  "title": "Κρυμμένο Μήνυμα",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #10, Θέμα 3",
   "url": "https://progintro.github.io/exams/2023/fall/ex10/",
   "years": [
    2023
   ]
  },
  "chapters": [
   18,
   14,
   13
  ],
  "topics": [
   "files",
   "strings",
   "dynamic-memory",
   "command-line-args"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α18.15",
  "path": "questions/exams/exam-2023-fall-ex10-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex10-q3.html",
  "statement": "Πρόγραμμα: `hidden.c`\n\nΓράψτε ένα πρόγραμμα που παίρνει ως όρισμα το όνομα ενός αρχείου που περιέχει ένα κείμενο με λέξεις που αποτελούνται από λατινικούς χαρακτήρες (a-zA-Z) και θετικούς ακεραίους που αντιστοιχούν στην θέση της κάθε λέξης μέσα στο κείμενο και τυπώνει αυτές τις λέξεις με την σειρά που δίνονται ως ορίσματα στο πρόγραμμα. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ gcc -o hidden hidden.c\n$ cat message.txt\nIn the quiet glade, where whispers of the past weave,\nBeneath the vault of heaven, a secret to conceive.\nThe oak, ancient and large, guards a mystery so deep,\nWithin its shadowed roots, a treasure lies asleep.\nHidden by time's embrace, under earth's tender keep,\nNear the tree, love's promise, forever to reap\n$ ./hidden message.txt 19 34 35 42 1 23 20 49\nThe treasure lies under the large oak tree\n$ ./hidden message.txt 19 34 35 29\nThe treasure lies Within\n```\n\nΠαρατηρούμε ότι η λέξη \"The\" τυπώνεται πρώτη καθώς είναι η 20η λέξη στο κείμενο, δηλαδή βρίσκεται στην θέση 19 και αυτός είναι ο πρώτος ακέραιος που δόθηκε ως όρισμα στην γραμμή εντολών μετά το αρχείο. Αντίστοιχα τυπώνονται και οι υπόλοιπες λέξεις.",
  "hint": "Χωρίστε το κείμενο σε λέξεις από λατινικούς χαρακτήρες (οτιδήποτε άλλο είναι διαχωριστικό, άρα το `time's` δίνει δύο λέξεις) και αποθηκεύστε τες σε δυναμικό πίνακα, ώστε να έχετε άμεση πρόσβαση με τη θέση. Οι θέσεις μετράνε από το 0· ελέγξτε θέσεις εκτός ορίων."
 },
 {
  "id": "exam-2023-fall-ex10-q4",
  "kind": "exam",
  "title": "Πλησιάζοντας στον Στόχο",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #10, Θέμα 4",
   "url": "https://progintro.github.io/exams/2023/fall/ex10/",
   "years": [
    2023
   ]
  },
  "chapters": [
   17,
   19,
   12
  ],
  "topics": [
   "sorting",
   "structs",
   "command-line-args",
   "floating-point"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α17.11",
  "path": "questions/exams/exam-2023-fall-ex10-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex10-q4.html",
  "statement": "Πρόγραμμα: `treasure.c`\n\nΓράψτε ένα πρόγραμμα το οποίο παίρνει ως ορίσματα από την γραμμή εντολών μια συντεταγμένη στόχο (goal) και στην συνέχεια ένα σύνολο άλλων συντεταγμένων (starting points) και τυπώνει όλες τις συντεταγμένες ταξινομημένες σε αύξουσα σειρά με βάση την απόστασή τους από τον στόχο. Όλοι οι αριθμοί κινητής υποδιαστολής θέλουμε να τυπώνονται με ακρίβεια με δύο δεκαδικών ψηφίων. Όλες οι συντεταγμένες είναι της μορφής x,y όπου x,y είναι αριθμοί κινητής υποδιαστολής. Η απόσταση δύο σημείων x1,y1 και x2,y2 δίνεται από την έκφραση:\n\n$$ \\sqrt{(x2 - x1)^2 + (y2 - y1)^2} $$\n\nΠαράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ gcc -o treasure treasure.c -lm\n$ ./treasure 17,42 3.01,50.5 27.27,7 32,65.1 25,4 77,42.42 50,50 30.30,12\n1. Point 3.01,50.50 is 16.37 steps away from the goal\n2. Point 32.00,65.10 is 27.54 steps away from the goal\n3. Point 30.30,12.00 is 32.82 steps away from the goal\n4. Point 50.00,50.00 is 33.96 steps away from the goal\n5. Point 27.27,7.00 is 36.48 steps away from the goal\n6. Point 25.00,4.00 is 38.83 steps away from the goal\n7. Point 77.00,42.42 is 60.00 steps away from the goal\n```",
  "hint": "Αναλύστε κάθε όρισμα `x,y` σε δύο `double` (π.χ. με `sscanf` ή `strtod`) και απορρίψτε όσα δεν έχουν αυτή τη μορφή. Κρατήστε κάθε σημείο σε ένα `struct` μαζί με την απόστασή του από τον στόχο και ταξινομήστε με `qsort`."
 },
 {
  "id": "exam-2023-fall-ex11-q1",
  "kind": "exam",
  "title": "Αναζητώντας τον Blinky",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #11, Θέμα 1",
   "url": "https://progintro.github.io/exams/2023/fall/ex11/",
   "years": [
    2023
   ]
  },
  "chapters": [
   9,
   14
  ],
  "topics": [
   "input-output",
   "strings"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α9.27",
  "path": "questions/exams/exam-2023-fall-ex11-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex11-q1.html",
  "statement": "Πρόγραμμα: `blinky.c`\n\nΓράψτε ένα πρόγραμμα το οποίο διαβάζει κείμενο από την πρότυπη είσοδο (stdin) και το τυπώνει στην πρότυπη έξοδο (stdout) με τους εξής περιορισμούς:\n1. Κάθε φορά που βρίσκει την λέξη Blinky - να την τοποθετεί ανάμεσα σε αστεράκια '*' και να την κάνει να αναβοσβήνει (blink).\n1. Αν το string Blinky είναι μέρος άλλης λέξης δεν χρειάζεται κάποια αλλαγή.\n1. Οι λέξεις αποτελούνται μόνο από λατινικούς χαρακτήρες (A-Za-z) οποιοσδήποτε άλλος χαρακτήρας θεωρείται διαχωριστικό λέξεων.\n\nΠαράδειγμα εκτέλεσης ακολουθεί:\n\n[![asciicast](https://asciinema.org/a/js20ZyFDDS0t8ocszkBBo6b4J.svg)](https://asciinema.org/a/js20ZyFDDS0t8ocszkBBo6b4J)\n\nΑν για κάποιο λόγο δεν παίζει το παραπάνω link:\n\n```text\n$ gcc -o blinky blinky.c\n$ cat description.txt\nIn the Pac-Man universe, Blinky is the red ghost who\npersistently chases the game's hero, earning the\nnickname \"Shadow\" for his relentless pursuit.\nBlinky's strategy intensifies as Pac-Man consumes\nmore dots, making Blinky a formidable challenge and\na central figure in game strategy. His vivid red hue\nnot only marks Blinky as the primary antagonist but\nalso signals the immediate threat he poses.\n$ ./blinky < description.txt\nIn the Pac-Man universe, *Blinky* is the red ghost who\npersistently chases the game's hero, earning the\nnickname \"Shadow\" for his relentless pursuit.\n*Blinky*'s strategy intensifies as Pac-Man consumes\nmore dots, making *Blinky* a formidable challenge and\na central figure in game strategy. His vivid red hue\nnot only marks *Blinky* as the primary antagonist but\nalso signals the immediate threat he poses.\n```",
  "hint": "Μαζέψτε κάθε λέξη (μέγιστη ακολουθία λατινικών χαρακτήρων) σε έναν buffer και, όταν τελειώσει, συγκρίνετέ τη ολόκληρη με το `Blinky`· έτσι το `Blinky` μέσα σε μεγαλύτερη λέξη δεν αλλάζει. Οι διαχωριστικοί χαρακτήρες τυπώνονται αυτούσιοι. Το «έντονο» (και αντίστοιχα το πλάγιο ή το αναβόσβημα) στο τερματικό γίνεται με ακολουθίες διαφυγής ANSI (ANSI escape codes) που τυπώνετε πριν και μετά το κείμενο, π.χ. `\\033[...m`· ψάξτε ποιος κωδικός αντιστοιχεί στο εφέ που θέλετε και ποιος τα επαναφέρει."
 },
 {
  "id": "exam-2023-fall-ex11-q2",
  "kind": "exam",
  "title": "Τοποθέτηση του Pacman",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #11, Θέμα 2",
   "url": "https://progintro.github.io/exams/2023/fall/ex11/",
   "years": [
    2023
   ]
  },
  "chapters": [
   10,
   12
  ],
  "topics": [
   "arrays",
   "command-line-args"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α10.20",
  "path": "questions/exams/exam-2023-fall-ex11-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex11-q2.html",
  "statement": "Πρόγραμμα: `position.c`\n\nΓράψτε ένα πρόγραμμα που παίρνει ως πρώτο όρισμα την διάσταση ενός τετραγωνικού πλέγματος και ως υπόλοιπα ορίσματα τις θέσεις των φαντασμάτων (ghosts) του pacman και τυπώνει όλες τις θέσεις στο πλέγμα που θα μπορούσε να τοποθετηθεί ο pacman. Ο pacman δεν μπορεί να τοποθετηθεί στην ίδια γραμμή ή στήλη με κάποιο φάντασμα. Όλες οι διαστάσεις δίνονται ως \"x,y\" ορίσματα (όπου x, y είναι ακέραιοι). Εάν δεν υπάρχει δυνατή τοποθέτηση το πρόγραμμά σας θα πρέπει να τυπώνει ανάλογο μήνυμα. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ gcc -o position position.c\n$ ./position 4 0,4 3,2 2,1 1,3\nPacman cannot be positioned anywhere\n$ ./position 4 0,4 3,2 2,1 0,3\nPacman can be positioned at: 1,0\n$ ./position 4 0,4 3,2 2,1\nPacman can be positioned at: 1,0\nPacman can be positioned at: 1,3\n$ ./position 4 1,2 2,1\nPacman can be positioned at: 0,0\nPacman can be positioned at: 0,3\nPacman can be positioned at: 3,0\nPacman can be positioned at: 3,3\n```",
  "hint": "Δεν χρειάζεστε ολόκληρο το πλέγμα: αρκούν δύο πίνακες σημαιών, ένας για τις γραμμές και ένας για τις στήλες που «καλύπτει» κάποιο φάντασμα. Κοιτάξτε στα παραδείγματα τι γίνεται με συντεταγμένες έξω από το πλέγμα (π.χ. `0,4` σε πλέγμα 4)."
 },
 {
  "id": "exam-2023-fall-ex11-q3",
  "kind": "exam",
  "title": "Κινήσεις σε Πλέγμα",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #11, Θέμα 3",
   "url": "https://progintro.github.io/exams/2023/fall/ex11/",
   "years": [
    2023
   ]
  },
  "chapters": [
   12,
   18
  ],
  "topics": [
   "multidim-arrays",
   "files",
   "simulation"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α12.17",
  "path": "questions/exams/exam-2023-fall-ex11-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex11-q3.html",
  "statement": "Πρόγραμμα: `pacman.c`\n\nΓράψτε ένα πρόγραμμα που παίρνει δύο ορίσματα: (1) το όνομα ενός αρχείου που περιέχει μια πίστα pacman και (2) τις κινήσεις που πρέπει να κάνει ο pacman πάνω στο πλέγμα και τυπώνει την τελική κατάσταση του παιχνιδιού μετά από αυτές τις κινήσεις. Το αρχείο θα έχει την ακόλουθη μορφή:\n1. Διάσταση του πλέγματος του παιχνιδιού (δεκαδικός ακέραιος).\n2. Τετράγωνο πλέγμα με χαρακτήρες '.' και ένα 'P' για την αρχική θέση του pacman. Όλοι οι άλλοι χαρακτήρες αγνοούνται.\nΟι κινήσεις που πρέπει να κάνει ο pacman θα αποτελούνται από 4 χαρακτήρες 'U' (Up), 'D' (Down), 'L' (Left), 'R' (Right). Όταν ο pacman κινείται σε κάποια θέση, τότε η τελεία ('.') σε εκείνη την θέση εξαφανίζεται. Η πίστα είναι τόρος, δηλαδή αν είσαι στην τελευταία γραμμή της και κινηθείς προς τα κάτω (D) τότε μεταφέρεσαι στην πρώτη γραμμή. Αντίστοιχα για κινήσεις αριστερά-δεξιά. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ gcc -o pacman pacman.c\n$ cat level.txt\n7\n.......\n.......\n..P....\n.......\n.......\n.......\n.......\n$ ./pacman level.txt RRD\n.......\n.......\n..   ..\n....P..\n.......\n.......\n.......\n$ ./pacman level.txt RRDDLL\n.......\n.......\n..   ..\n.... ..\n..P  ..\n.......\n.......\n$ ./pacman level.txt RRDDLLUU\n.......\n.......\n..P  ..\n.. . ..\n..   ..\n.......\n.......\n$ ./pacman level.txt RRDDLLUULLLL\n.......\n.......\n     P\n.. . ..\n..   ..\n.......\n.......\n```",
  "hint": "Φορτώστε την πίστα σε δισδιάστατο πίνακα, βρείτε το `P` και εφαρμόστε τις κινήσεις μία-μία, αφήνοντας κενό όπου περνάει ο pacman. Η αναδίπλωση του τόρου γίνεται με υπόλοιπο διαίρεσης· προσέξτε τις αρνητικές τιμές (`(x - 1 + n) % n`). Άγνωστος χαρακτήρας κίνησης είναι σφάλμα."
 },
 {
  "id": "exam-2023-fall-ex11-q4",
  "kind": "exam",
  "title": "Clyde Πρώτοι",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #11, Θέμα 4",
   "url": "https://progintro.github.io/exams/2023/fall/ex11/",
   "years": [
    2023
   ]
  },
  "chapters": [
   16,
   2
  ],
  "topics": [
   "math-algorithms",
   "loops",
   "integer-representation"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α16.21",
  "path": "questions/exams/exam-2023-fall-ex11-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex11-q4.html",
  "statement": "Πρόγραμμα: `clyde.c`\n\nΈνας ακέραιος λέγεται πρώτος όταν διαιρείται μόνο με τον εαυτό του και την μονάδα. Ένας πρώτος λέγεται clyde πρώτος όταν υπάρχει μια περιστροφή των ψηφίων του (με βάση το 10) που είναι επίσης πρώτος. Γράψτε ένα πρόγραμμα που παίρνει έναν ακέραιο από την κονσόλα και αποφαίνεται αν είναι Clyde πρώτος ή όχι. Παραδείγματα εκτέλεσης:\n\n```text\n$ gcc -o clyde clyde.c -lm\n$ ./clyde 13\n13 is a clyde prime because 31 is prime too\n$ ./clyde 99923\n99923 is a clyde prime because 92399 is prime too\n$ ./clyde 41\n41 is NOT a clyde prime\n$ ./clyde 99924\n99924 is NOT a clyde prime\n$ ./clyde 90000520793\n90000520793 is a clyde prime because 93900005207 is prime too\n```",
  "hint": "Γράψτε μια συνάρτηση ελέγχου πρώτου που δοκιμάζει διαιρέτες ως τη ρίζα του αριθμού, με `long long` αφού τα παραδείγματα ξεπερνούν το `int`. Οι περιστροφές παράγονται αριθμητικά με `/` και `%` δυνάμεων του 10· σκεφτείτε τι γίνεται όταν μια περιστροφή ξεκινά με 0 και αν μετράει ο ίδιος ο αριθμός."
 },
 {
  "id": "exam-2023-fall-ex12-q1",
  "kind": "exam",
  "title": "Γραμμή και Γράμμα",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #12, Θέμα 1",
   "url": "https://progintro.github.io/exams/2023/fall/ex12/",
   "years": [
    2023
   ]
  },
  "chapters": [
   9,
   10
  ],
  "topics": [
   "input-output",
   "arrays"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α9.20",
  "path": "questions/exams/exam-2023-fall-ex12-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex12-q1.html",
  "statement": "Πρόγραμμα: `letter.c`\n\nΓράψτε ένα πρόγραμμα το οποίο διαβάζει από την πρότυπη είσοδο (stdin) μια σειρά από γραμμές που περιέχουν τα γράμματα μιας λέξης (ένα γράμμα ανά γραμμή με χρήση underscore '_' για όλα τα γράμματα που δεν αποκαλύπτονται σε εκείνη την γραμμή) και τυπώνει στην πρότυπη έξοδο (stdout) την λέξη που δόθηκε. Η είσοδος θα αποτελείται μόνο από λατινικούς (A-Za-z) χαρακτήρες, underscores και αλλαγές γραμμής. Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ gcc -o letter letter.c\n$ cat reveal.txt\n__r_____\n_______l\n_a______\n___n____\n_____v__\nc_______\n______a_\n____i___\n$ ./letter < reveal.txt\ncarnival\n```",
  "hint": "Κάθε γραμμή έχει το ίδιο μήκος με τη λέξη και αποκαλύπτει ένα γράμμα στη θέση του. Διαβάστε χαρακτήρα-χαρακτήρα κρατώντας τη στήλη στην οποία βρίσκεστε και γράψτε κάθε γράμμα στη θέση του σε έναν πίνακα. Ελέγξτε για χαρακτήρες εκτός προδιαγραφών και γραμμές διαφορετικού μήκους."
 },
 {
  "id": "exam-2023-fall-ex12-q2",
  "kind": "exam",
  "title": "Προσεγγίζοντας την Λέξη",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #12, Θέμα 2",
   "url": "https://progintro.github.io/exams/2023/fall/ex12/",
   "years": [
    2023
   ]
  },
  "chapters": [
   14,
   10
  ],
  "topics": [
   "strings",
   "command-line-args",
   "arrays"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α14.15",
  "path": "questions/exams/exam-2023-fall-ex12-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex12-q2.html",
  "statement": "Πρόγραμμα: `check.c`\n\nΓράψτε ένα πρόγραμμα που να δέχεται ως πρώτο όρισμα μια λέξη στόχο (goal) ακολουθούμενο από μια σειρά από προσπάθειες του χρήστη να μαντέψει την λέξη στόχο και να τυπώνει στην πρότυπη έξοδο την εγγύτητα της κάθε προσπάθειας στην λέξη στόχο. Η εγγύτητα της κάθε λέξης εξαρτάται από δύο μετρικές: (1) πόσα σωστά γράμματα μάντεψε ο χρήστης και είναι σε λάθος θέση και (2) πόσα σωστά γράμματα μάντεψε ο χρήστης και είναι στην σωστή θέση. Όλες οι λέξεις θα αποτελούνται από λατινικούς χαρακτήρες και θα έχουν το ίδιο μήκος. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ gcc -o check check.c\n$ ./check unlit legal vinyl sling inlet unlit\nlegal has 0 correct letters in correct position and 1 correct letters in an incorrect position\nvinyl has 0 correct letters in correct position and 3 correct letters in an incorrect position\nsling has 0 correct letters in correct position and 3 correct letters in an incorrect position\ninlet has 3 correct letters in correct position and 1 correct letters in an incorrect position\nunlit has 5 correct letters in correct position and 0 correct letters in an incorrect position\n$ ./check hello world worll wrllo\nworld has 1 correct letters in correct position and 1 correct letters in an incorrect position\nworll has 1 correct letters in correct position and 2 correct letters in an incorrect position\nwrllo has 3 correct letters in correct position and 0 correct letters in an incorrect position\n```",
  "hint": "Μετρήστε πρώτα τις ακριβείς θέσεις. Για τα γράμματα σε λάθος θέση, προσέξτε τα διπλά γράμματα: φτιάξτε πίνακες συχνοτήτων (26 θέσεις) μόνο για τα γράμματα που δεν ταίριαξαν ακριβώς, σε στόχο και προσπάθεια, και αθροίστε το ελάχιστο ανά γράμμα. Λέξεις με διαφορετικό μήκος είναι σφάλμα."
 },
 {
  "id": "exam-2023-fall-ex12-q3",
  "kind": "exam",
  "title": "Κρεμάλα",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #12, Θέμα 3",
   "url": "https://progintro.github.io/exams/2023/fall/ex12/",
   "years": [
    2023
   ]
  },
  "chapters": [
   14,
   18
  ],
  "topics": [
   "strings",
   "files"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α14.16",
  "path": "questions/exams/exam-2023-fall-ex12-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex12-q3.html",
  "statement": "Πρόγραμμα: `hangman.c`\n\nΓράψτε ένα πρόγραμμα που παίρνει ως πρώτο όρισμα το όνομα ενός αρχείου που περιέχει όλες τις επιτρεπτές λέξεις που μπορεί να βάλει κάποιος (μία ανά γραμμή) και ως δεύτερο όρισμα τα γράμματα της λέξης που έχουμε βρει σε ένα παιχνίδι κρεμάλας και τυπώνει στην πρότυπη έξοδο όλες τις πιθανές λέξεις που μπορεί να ταιριάζουν. Εάν δεν υπάρχει λέξη που να ταιριάζει, το πρόγραμμά σας θα πρέπει να τυπώνει ανάλογο μήνυμα. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ gcc -o hangman hangman.c\n$ cat words.txt\ncat\nDOG\nGiraffe\ntennis\nturtle\n$ ./hangman words.txt t_____\ntennis\nturtle\n$ ./hangman words.txt __r___\nturtle\n$ ./hangman words.txt ___\ncat\nDOG\n$ ./hangman words.txt d__\nDOG\n$ ./hangman words.txt _e_e__\nNo words matching guess found\n$ ./hangman /usr/share/dict/words __ou________ing\ntroubleshooting\n```",
  "hint": "Διαβάστε το λεξικό γραμμή-γραμμή και κρατήστε μόνο λέξεις με το ίδιο μήκος με το μοτίβο. Το `_` ταιριάζει με οποιοδήποτε γράμμα, ενώ τα γράμματα συγκρίνονται χωρίς διάκριση πεζών-κεφαλαίων (`tolower`). Μην ξεχάσετε να αφαιρέσετε το `'\\n'` στο τέλος κάθε γραμμής."
 },
 {
  "id": "exam-2023-fall-ex12-q4",
  "kind": "exam",
  "title": "Εαυτοί Αριθμοί",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #12, Θέμα 4",
   "url": "https://progintro.github.io/exams/2023/fall/ex12/",
   "years": [
    2023
   ]
  },
  "chapters": [
   16,
   10
  ],
  "topics": [
   "math-algorithms",
   "arrays",
   "loops"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α16.22",
  "path": "questions/exams/exam-2023-fall-ex12-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex12-q4.html",
  "statement": "Πρόγραμμα: `self.c`\n\nΣτην θεωρία αριθμών, ένας φυσικός αριθμός $n$ λέγεται εαυτός (self) όταν δεν υπάρχει κάποιος φυσικός αριθμός $m$, έτσι ώστε το $n$ να ισούται με το άθροισμα του $m$ και των ψηφίων του $m$ (με βάση το 10 σε αυτό το θέμα). Έστω $F(n)$ η συνάρτηση που υπολογίζει το άθροισμα ενός φυσικού $n$ και των ψηφίων του. Τότε ένας αριθμός $n$ είναι εαυτός αν και μόνο αν $\\nexists m . F(m) = n$. Για παράδειγμα, $F(15) = 15 + 1 + 5 = 21$ και επομένως ο αριθμός 21 δεν είναι εαυτός. Αντίθετα, ο αριθμός 20 είναι εαυτός καθώς δεν υπάρχει φυσικός αριθμός m έτσι ώστε $F(m) = 20$. Υπάρχουν μόλις 13 εαυτοί αριθμοί μικρότεροι του 100:\n\n$$ 1, 3, 5, 7, 9, 20, 31, 42, 53, 64, 75, 86, 97 $$\n\nΓράψτε ένα πρόγραμμα C το οποίο βρίσκει και τυπώνει όλους τους εαυτούς αριθμούς σε ένα εύρος φυσικών αριθμών $[low, high]$ (το εύρος είναι κλειστό, δηλαδή τα άκρα συμπεριλαμβάνονται), όπου οι αριθμοί δίνονται από την γραμμή εντολών. Ακολουθεί παράδειγμα εκτέλεσης για να βρούμε όλους τους εαυτούς αριθμούς στο διάστημα $[9900, 10000]$:\n\n```text\n$ gcc -o self self.c\n$ ./self 9900 10000\nSelf numbers: 9903 9914 9925 9927 9938 9949 9960 9971 9982 9993\nFound 10 total\n```",
  "hint": "Γράψτε τη συνάρτηση F(m) με άθροισμα ψηφίων. Αντί να ψάχνετε για κάθε n ένα m, σημαδέψτε σε έναν πίνακα όλες τις τιμές F(m) που πέφτουν στο [low, high]· αρκεί να δοκιμάσετε m λίγο μικρότερα από το low (το άθροισμα ψηφίων είναι μικρό). Ελέγξτε ότι low ≤ high."
 },
 {
  "id": "exam-2023-fall-ex13-q1",
  "kind": "exam",
  "title": "Κάντο όπως ο Βιετά",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #13, Θέμα 1",
   "url": "https://progintro.github.io/exams/2023/fall/ex13/",
   "years": [
    2023
   ]
  },
  "chapters": [
   6,
   3,
   4
  ],
  "topics": [
   "floating-point",
   "loops",
   "math-algorithms"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α6.22",
  "path": "questions/exams/exam-2023-fall-ex13-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex13-q1.html",
  "statement": "Πρόγραμμα: `vieta.c`\n\nΟ Γάλλος μαθηματικός Βιετά (Francois Viete) υπήρξε ο πρώτος μαθηματικός που χρησιμοποίησε ευρέως σύμβολα για να εκφράσει αριθμητικές ποσότητες. Το 1593 κατάφερε να εκφράσει και να υπολογίσει τον αριθμό $\\pi$ με ακρίβεια 9 δεκαδικών, βελτιώνοντας έτσι το σχετικό αποτέλεσμα του Αρχιμήδη. Για να υπολογίσει το $\\pi$, ο Βιετά χρησιμοποίησε μια σχέση που χρησιμοποιεί ένα απειρογινόμενο όρων $t_i$, γνωστό ως φόρμουλα Βιετά προς τιμήν του:\n\n$$ \\frac{2}{\\pi} = \\underbrace{\\frac{\\sqrt{2}}{2}}_{t_1} \\cdot \\underbrace{\\frac{\\sqrt{2+\\sqrt{2}}}{2}}_{t_2} \\cdot \\underbrace{\\frac{\\sqrt{2+\\sqrt{2+\\sqrt{2}}}}{2}}_{t_3} \\cdots $$\n\nΛύνοντας την παραπάνω σχέση ως προς $\\pi$, μπορούμε και εμείς να προσεγγίσουμε το $\\pi$ όπως ο Βιετά. Μάλιστα, όσους περισσότερους όρους $t_i$ χρησιμοποιούμε, τόσο καλύτερη η προσέγγισή μας. Γράψτε ένα πρόγραμμα C το οποίο παίρνει έναν θετικό ακέραιο ως όρισμα από την γραμμή εντολών που αντιπροσωπεύει πόσους πρώτους όρους $t_i$ να χρησιμοποιήσει στον υπολογισμό του $\\pi$ και στην συνέχεια εκτυπώνει την προσέγγιση του $\\pi$ με 9 δεκαδικά ψηφία. Παραδείγματα εκτέλεσης είναι τα εξής:\n\n```text\n$ gcc -o vieta vieta.c -lm\n$ ./vieta 2\nMultiplied first 2 ti terms, pi = 3.061467459\n$ ./vieta 5\nMultiplied first 5 ti terms, pi = 3.140331157\n$ ./vieta 50\nMultiplied first 50 ti terms, pi = 3.141592654\n```",
  "hint": "Κάθε αριθμητής προκύπτει από τον προηγούμενο: αν ο αριθμητής του t_i είναι a, ο επόμενος είναι √(2 + a). Πολλαπλασιάστε τους πρώτους N όρους σε έναν `double` και λύστε τη σχέση ως προς π. Χρειάζεστε `math.h` και `-lm`, και έλεγχο ότι το όρισμα είναι θετικός ακέραιος."
 },
 {
  "id": "exam-2023-fall-ex13-q2",
  "kind": "exam",
  "title": "Αλλαγή Τέρματος",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #13, Θέμα 2",
   "url": "https://progintro.github.io/exams/2023/fall/ex13/",
   "years": [
    2023
   ]
  },
  "chapters": [
   12,
   9,
   13
  ],
  "topics": [
   "multidim-arrays",
   "dynamic-memory",
   "input-output",
   "input-validation"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α12.13",
  "path": "questions/exams/exam-2023-fall-ex13-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex13-q2.html",
  "statement": "Πρόγραμμα: `change.c`\n\nΓράψτε ένα πρόγραμμα το οποίο διαβάζει από την πρότυπη είσοδο (stdin) την μορφή ενός ποδοσφαιρικού γηπέδου σε ορθογώνια μορφή και την τυπώνει στην πρότυπη έξοδο (stdout) μετά από περιστροφή 180 μοιρών. Στην πρώτη γραμμή δίνονται οι ακέραιες διαστάσεις του γηπέδου (πλάτος και μήκος) και στην συνέχεια δίνονται τα περιεχόμενα του γηπέδου ως ακέραιοι - οι παίκτες της 1ης ομάδας αναπαρίστανται με 1, της 2ης ομάδας με 2 και ο κενός χώρος με 0. Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ gcc -o change change.c\n$ cat field.txt\n9 31\n0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0\n0 0 0 0 2 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 1 0 0 0 0 0\n0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 1 0 0 0 0 0 0 0 0\n0 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 0 0 0 0\n2 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 1 0\n0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0\n0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0\n0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n$ ./change < field.txt\n0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0\n0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0\n0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0\n0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0\n0 1 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 2\n0 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 0 0 0 0\n0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0\n0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 2 0 0 0 0\n0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n```",
  "hint": "Η περιστροφή κατά 180 μοίρες αντιστρέφει και τη σειρά των γραμμών και τη σειρά των στοιχείων κάθε γραμμής. Διαβάστε τις διαστάσεις, δεσμεύστε δυναμικά χώρο και ελέγξτε ότι κάθε τιμή είναι 0, 1 ή 2 και ότι το πλήθος τους είναι σωστό."
 },
 {
  "id": "exam-2023-fall-ex13-q3",
  "kind": "exam",
  "title": "Πρωτάθλημα",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #13, Θέμα 3",
   "url": "https://progintro.github.io/exams/2023/fall/ex13/",
   "years": [
    2023
   ]
  },
  "chapters": [
   19,
   17,
   18
  ],
  "topics": [
   "structs",
   "sorting",
   "files",
   "strings"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α19.11",
  "path": "questions/exams/exam-2023-fall-ex13-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex13-q3.html",
  "statement": "Πρόγραμμα: `league.c`\n\nΓράψτε ένα πρόγραμμα το οποίο παίρνει ως όρισμα ένα αρχείο με αποτελέσματα αγώνων ανάμεσα σε ομάδες και στο τέλος τυπώνει όλες τις ομάδες ταξινομημένες σε αύξουσα σειρά με βάση την βαθμολογία τους. Σε περίπτωση ισοβαθμίας, χρησιμοποιούμε την διαφορά γκολ για να αποφασίσουμε ποια ομάδα είναι πρώτη. Μια ομάδα παίρνει 3 βαθμούς σε περίπτωση νίκης, 1 βαθμό σε περίπτωση ισοπαλίας και 0 βαθμούς εάν χάσει. Το αρχείο θα περιέχει έναν αγώνα ανά γραμμή και η μορφή του θα είναι: ΟΜΑΔΑ1-ΟΜΑΔΑ2,ΓΚΟΛ1-ΓΚΟΛ2 όπου ΓΚΟΛ1 είναι τα γκολ που έβαλε η ΟΜΑΔΑ1 και αντίστοιχα για τα ΓΚΟΛ2/ΟΜΑΔΑ2. Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ gcc -o league league.c\n$ cat games.txt\nΑΕΚ-Πανιώνιος,4-2\nΙωνικός-Παναχαϊκή,3-0\nΞάνθη-Ολυμπιακός,1-5\nΠαναθηναϊκός-Ακράτητος,3-1\nΆρης-Ηρακλής,2-2\nΠΑΟΚ-ΠΑΣ Γιάννινα,2-3\nΠΑΟΚ-Παναχαϊκή,2-0\nΞάνθη-Ηρακλής,1-2\nΟλυμπιακός-ΠΑΣ Γιάννινα,1-0\nΠανιώνιος-Παναθηναϊκός,0-2\nΆρης-ΑΕΚ,2-2\nΙωνικός-Ακράτητος,3-3\n$ ./league games.txt\nΟλυμπιακός, 6, (6 - 1)\nΠαναθηναϊκός, 6, (5 - 1)\nΙωνικός, 4, (6 - 3)\nΑΕΚ, 4, (6 - 4)\nΗρακλής, 4, (4 - 3)\nΠΑΟΚ, 3, (4 - 3)\nΠΑΣ Γιάννινα, 3, (3 - 3)\nΆρης, 2, (4 - 4)\nΑκράτητος, 1, (4 - 6)\nΠανιώνιος, 0, (2 - 6)\nΞάνθη, 0, (2 - 7)\nΠαναχαϊκή, 0, (0 - 5)\n```",
  "hint": "Κρατήστε ένα `struct` ανά ομάδα (όνομα, βαθμοί, γκολ υπέρ, γκολ κατά) σε δυναμικό πίνακα, και για κάθε αγώνα βρείτε ή προσθέστε τις δύο ομάδες. Τα ονόματα είναι UTF-8 και μπορεί να έχουν κενά, οπότε χωρίστε τη γραμμή στα `-` και `,` και όχι στα κενά. Ταξινομήστε με `qsort` με βαθμούς και μετά διαφορά γκολ."
 },
 {
  "id": "exam-2023-fall-ex13-q4",
  "kind": "exam",
  "title": "Τυχεροί Αριθμοί",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #13, Θέμα 4",
   "url": "https://progintro.github.io/exams/2023/fall/ex13/",
   "years": [
    2023
   ]
  },
  "chapters": [
   16,
   2
  ],
  "topics": [
   "math-algorithms",
   "loops",
   "integer-representation",
   "floating-point"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α16.23",
  "path": "questions/exams/exam-2023-fall-ex13-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex13-q4.html",
  "statement": "Πρόγραμμα: `lucky.c`\n\nΓράψτε ένα πρόγραμμα που να ελέγχει για κάθε ένα ακέραιο όρισμα που του δίνεται εάν ο αριθμός αυτός είναι \"τυχερός\" (lucky). Ένας ακέραιος λέγεται τυχερός, εάν μπορεί να εκφραστεί ως το άθροισμα των κύβων δύο θετικών ακεραίων. Για παράδειγμα, ο αριθμός 28 είναι τυχερός (3^3 + 1^3) ενώ ο αριθμός 27 δεν είναι. Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ gcc -o lucky lucky.c -lm\n$ ./lucky 28 95 128 298374 508167898112\n28 is lucky: 1^3 + 3^3 = 28\nNo positive i, j exist such that i^3+j^3 = 95\n128 is lucky: 4^3 + 4^3 = 128\nNo positive i, j exist such that i^3+j^3 = 298374\n508167898112 is lucky: 2344^3 + 7912^3 = 508167898112\n```",
  "hint": "Για κάθε i με i³ ≤ n/2 αρκεί να ελέγξετε αν το n − i³ είναι τέλειος κύβος. Αν χρησιμοποιήσετε `cbrt`, στρογγυλέψτε και επαληθεύστε με ακέραια αριθμητική, γιατί η κινητή υποδιαστολή κάνει λάθη στρογγύλευσης. Το τελευταίο παράδειγμα χρειάζεται `long long`."
 },
 {
  "id": "exam-2023-fall-ex14-q1",
  "kind": "exam",
  "title": "Ορεκτικό",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #14, Θέμα 1",
   "url": "https://progintro.github.io/exams/2023/fall/ex14/",
   "years": [
    2023
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α9.21",
  "path": "questions/exams/exam-2023-fall-ex14-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex14-q1.html",
  "statement": "Πρόγραμμα: `steak.c`\n\nΓράψτε ένα πρόγραμμα που διαβάζει από την πρότυπη είσοδο (stdin) ένα κείμενο και το τυπώνει στην πρότυπη έξοδο (stdout) αφού πρώτα προσθέσει μια μπριζόλα (χαρακτήρας unicode U+1F969)  στην αρχή και στο τέλος κάθε γραμμής. Το υπόλοιπο της πρότασης δεν πρέπει να αλλάζει. Το πρόγραμμά σας πρέπει να χειρίζεται γραμμές οποιουδήποτε μήκους. Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ cat message.txt\nCome savor the pleasure, of treasures beyond measure,\nIn our cozy abode, where gourmet is the code�\nWe await your presence, for an experience quintessence,\nAt our steakhouse divine, where dining is fine!\n$ gcc -o steak steak.c\n$ ./steak  < message.txt\n🥩Come savor the pleasure, of treasures beyond measure,🥩\n🥩In our cozy abode, where gourmet is the code�🥩\n🥩We await your presence, for an experience quintessence,🥩\n🥩At our steakhouse divine, where dining is fine!🥩\n```\n\n> Σημείωση: στο πρωτότυπο το παράδειγμα δίνεται ως στιγμιότυπο τερματικού ([steak.png](https://progintro.github.io/exams/2023/fall/ex14/images/steak.png)) και εδώ μεταγράφεται ως κείμενο· ο χαρακτήρας � είναι ένα byte του αρχείου που δεν είναι έγκυρο UTF-8.",
  "hint": "Δεν χρειάζεται να αποθηκεύσετε γραμμές: με `getchar` τυπώστε τη μπριζόλα στην αρχή κάθε γραμμής και πριν από κάθε `'\\n'`. Ο χαρακτήρας U+1F969 στο UTF-8 είναι μια ακολουθία 4 bytes που μπορείτε να γράψετε ως string. Σκεφτείτε την τελευταία γραμμή χωρίς `'\\n'` και την κενή είσοδο."
 },
 {
  "id": "exam-2023-fall-ex14-q2",
  "kind": "exam",
  "title": "Μένοντας στις Σωστές Θερμίδες",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #14, Θέμα 2",
   "url": "https://progintro.github.io/exams/2023/fall/ex14/",
   "years": [
    2023
   ]
  },
  "chapters": [
   25,
   17
  ],
  "topics": [
   "sorting",
   "problem-solving",
   "command-line-args",
   "input-validation"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α25.6",
  "path": "questions/exams/exam-2023-fall-ex14-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex14-q2.html",
  "statement": "Πρόγραμμα: `right.c`\n\nΓράψτε ένα πρόγραμμα το οποίο δέχεται ως πρώτο όρισμα ένα σύνολο θερμίδων το οποίο δεν πρέπει να υπερβούμε και τα υπόλοιπα ορίσματα είναι οι θερμίδες που περιέχει κάθε πιάτο μπροστά μας και τυπώνει τον μέγιστο αριθμό πιάτων που μπορούμε να φάμε χωρίς να υπερβούμε το όριο θερμίδων. Οι θερμίδες μπορούν να είναι μόνο θετικοί ακέραιοι και κάθε όρισμα αντιστοιχεί σε ακριβώς ένα πιάτο μπροστά μας (δεν μπορούμε να φάμε το ίδιο πιάτο δύο φορές!). Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ gcc -o right right.c\n$ ./right\nNeed a target set of calories\n$ ./right 100 101\nWithin 100 calories we can fit 0 different plates\n$ ./right 100 30 70 20 85 15 9 50\nWithin 100 calories we can fit 4 different plates\n$ ./right 1000 29 37 982 3 38 3899 22 737 89 478 27892 787 2897\nWithin 1000 calories we can fit 7 different plates\n```",
  "hint": "Σκεφτείτε ποια πιάτα συμφέρει να διαλέξετε πρώτα αν θέλετε όσο το δυνατόν περισσότερα· η ταξινόμηση βοηθά. Ελέγξτε ότι όλα τα ορίσματα είναι θετικοί ακέραιοι."
 },
 {
  "id": "exam-2023-fall-ex14-q3",
  "kind": "exam",
  "title": "Μετρήσεις Θερμοκρασίας",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #14, Θέμα 3",
   "url": "https://progintro.github.io/exams/2023/fall/ex14/",
   "years": [
    2023
   ]
  },
  "chapters": [
   18,
   19,
   17
  ],
  "topics": [
   "sorting",
   "structs",
   "files",
   "floating-point"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α18.16",
  "path": "questions/exams/exam-2023-fall-ex14-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex14-q3.html",
  "statement": "Πρόγραμμα: `templog.c`\n\nΓράψτε ένα πρόγραμμα το οποίο παίρνει ως όρισμα ένα αρχείο με μετρήσεις ενός θερμομέτρου στην διάρκεια του χρόνου το οποίο να τυπώνει στην πρότυπη έξοδο την μέση θερμοκρασία όλων των μετρήσεων και στην συνέχεια να τυπώνει όλες τις θερμοκρασίες ταξινομημένες με αύξουσα σειρά με βάση την απόστασή τους από την μέση θερμοκρασία. Το αρχείο με τις μετρήσεις θα έχει την μορφή \"ώρα μέτρησης,θερμοκρασία\" όπου η θερμοκρασία θα είναι ένας αριθμός κινητής υποδιαστολής. Η μέση θερμοκρασία θέλουμε να τυπωθεί με 3 δεκαδικά ψηφία. Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ cat log.txt\n2024-03-07 10:18:27,205.00\n2024-03-07 10:19:27,220.50\n2024-03-07 10:20:27,221.00\n2024-03-07 10:21:27,223.80\n2024-03-07 10:22:27,229.32\n2024-03-07 10:23:27,230.50\n2024-03-07 10:24:27,223.00\n2024-03-07 10:25:27,223.50\n2024-03-07 10:26:27,220.75\n2024-03-07 10:27:27,219.50\n$ gcc -o templog templog.c\n$ ./templog log.txt\nAverage temperature: 221.687\n2024-03-07 10:20:27,221.00\n2024-03-07 10:26:27,220.75\n2024-03-07 10:19:27,220.50\n2024-03-07 10:24:27,223.00\n2024-03-07 10:25:27,223.50\n2024-03-07 10:21:27,223.80\n2024-03-07 10:27:27,219.50\n2024-03-07 10:22:27,229.32\n2024-03-07 10:23:27,230.50\n2024-03-07 10:18:27,205.00\n```",
  "hint": "Διαβάστε κάθε γραμμή, χωρίστε στο κόμμα και κρατήστε την αρχική γραμμή μαζί με τη θερμοκρασία σε ένα `struct`. Υπολογίστε τον μέσο όρο και ταξινομήστε με `qsort` κατά `fabs(t - μέσος)`. Το πλήθος των μετρήσεων είναι άγνωστο, οπότε ο πίνακας μεγαλώνει με `realloc`."
 },
 {
  "id": "exam-2023-fall-ex14-q4",
  "kind": "exam",
  "title": "Τρόποι να Φάμε Παϊδάκια",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #14, Θέμα 4",
   "url": "https://progintro.github.io/exams/2023/fall/ex14/",
   "years": [
    2023
   ]
  },
  "chapters": [
   25,
   16
  ],
  "topics": [
   "dynamic-programming",
   "recursion",
   "math-algorithms",
   "integer-representation"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α25.10",
  "path": "questions/exams/exam-2023-fall-ex14-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex14-q4.html",
  "statement": "Πρόγραμμα: `chops.c`\n\nΟ Θάνος μόλις παρήγγειλε Ν παϊδάκια (τουλάχιστον 3) και αναρωτιέται με πόσους διαφορετικούς τρόπους μπορεί να τα φάει. Ξέρει ότι με κάθε του μπουκιά μπορεί να φάει 1 ή 2 παϊδάκια. Επειδή πεινάει πολύ σκοπεύει να φάει 3 παϊδάκια με ακριβώς μία μπουκιά. Για παράδειγμα, αν του φέρουν 5 παϊδάκια, μπορεί να τα φάει με 5 τρόπους: 1-1-3 (1 με μια μπουκιά, 1 με μια μπουκιά, 3 με μια μπουκιά), 1-3-1, 3-1-1, 2-3 και 3-2. Αν του φέρουν 3 παϊδάκια υπάρχει ακριβώς ένας τρόπος (3 με την μία). Αν του φέρουν 4 υπάρχουν 2 τρόποι (1-3, 3-1). Γράψτε ένα πρόγραμμα το οποίο παίρνει τον αριθμό από τα παϊδάκια ως ακέραιο όρισμα και τυπώνει τον αριθμό των διαφορετικών τρόπων με τους οποίους ο Θάνος μπορεί να τα φάει όλα. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ ./chops 2\nI would never order less than 3 chops.\n$ ./chops 3\nThere are 1 different ways to eat 3 chops.\n$ ./chops 4\nThere are 2 different ways to eat 4 chops.\n$ ./chops 5\nThere are 5 different ways to eat 5 chops.\n$ ./chops 6\nThere are 10 different ways to eat 6 chops.\n$ ./chops 50\nThere are 168903452400 different ways to eat 50 chops.\n```",
  "hint": "Βρείτε πρώτα με πόσους τρόπους τρώγονται k παϊδάκια μόνο με μπουκιές 1 ή 2 (αναδρομική σχέση). Μετά σκεφτείτε πού μπορεί να μπει η μοναδική μπουκιά των 3 και τι μένει αριστερά και δεξιά της. Για N = 50 χρειάζεστε `long long` και αποφυγή της εκθετικής αναδρομής (υπολογισμός από κάτω προς τα πάνω)."
 },
 {
  "id": "exam-2023-fall-ex15-q1",
  "kind": "exam",
  "title": "Πλαγιαστά Γράμματα",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #15, Θέμα 1",
   "url": "https://progintro.github.io/exams/2023/fall/ex15/",
   "years": [
    2023
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α9.22",
  "path": "questions/exams/exam-2023-fall-ex15-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex15-q1.html",
  "statement": "Πρόγραμμα: `italics.c`\n\nΓράψτε ένα πρόγραμμα που διαβάζει από την πρότυπη είσοδο (stdin) ένα κείμενο και το τυπώνει στην πρότυπη έξοδο (stdout) αφού πρώτα μετατρέψει τα γράμματα εντός των αστερίσκων (*) σε πλαγιαστά γράμματα (italics). Τα γράμματα που βρίσκονται εκτός αστερίσκων δεν χρειάζεται να αλλαχθούν. Οι αστερίσκοι θα παραλείπονται στην έξοδο του προγράμματος. Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ cat ithaca.txt\nAs you set out for Ithaka\nhope your road is a *long one*,\nfull of adventure, *full of discovery*.\nLaistrygonians, Cyclops,\nangry Poseidon *do not be afraid of them*.\n$ gcc -o italics italics.c\n$ ./italics < ithaca.txt\nAs you set out for Ithaka\nhope your road is a long one,\nfull of adventure, full of discovery.\nLaistrygonians, Cyclops,\nangry Poseidon do not be afraid of them.\n```\n\n> Σημείωση: στο πρωτότυπο το παράδειγμα δίνεται ως στιγμιότυπο τερματικού ([italics.png](https://progintro.github.io/exams/2023/fall/ex15/images/italics.png)) και εδώ μεταγράφεται ως κείμενο: στην έξοδο τα κείμενα «long one», «full of discovery» και «do not be afraid of them» εμφανίζονται πλάγια.",
  "hint": "Κρατήστε μια σημαία «είμαι μέσα σε αστερίσκους» που αλλάζει σε κάθε `*`, και τυπώστε τους υπόλοιπους χαρακτήρες όπως είναι. Το «έντονο» (και αντίστοιχα το πλάγιο ή το αναβόσβημα) στο τερματικό γίνεται με ακολουθίες διαφυγής ANSI (ANSI escape codes) που τυπώνετε πριν και μετά το κείμενο, π.χ. `\\033[...m`· ψάξτε ποιος κωδικός αντιστοιχεί στο εφέ που θέλετε και ποιος τα επαναφέρει."
 },
 {
  "id": "exam-2023-fall-ex15-q2",
  "kind": "exam",
  "title": "Τυπώνοντας τον Πίνακα ASCII",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #15, Θέμα 2",
   "url": "https://progintro.github.io/exams/2023/fall/ex15/",
   "years": [
    2023
   ]
  },
  "chapters": [
   6,
   2,
   4
  ],
  "topics": [
   "loops",
   "input-output",
   "computers",
   "command-line-args"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α6.23",
  "path": "questions/exams/exam-2023-fall-ex15-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex15-q2.html",
  "statement": "Πρόγραμμα: `ascii.c`\n\nΓράψτε ένα πρόγραμμα το οποίο δέχεται ως πρώτο όρισμα τον αριθμό στηλών που θέλουμε να χρησιμοποιήσει για τον πίνακα ASCII και στην συνέχεια τυπώνει τον πίνακα στην πρότυπη έξοδο. Οι χαρακτήρες πρέπει να τυπώνονται με την σειρά ο ένας κάτω από τον άλλο μέχρι να περάσουμε στην επόμενη στήλη. Για κάθε χαρακτήρα πρέπει να τυπώνεται: \"χαρακτήρας: δεκαεξαδική αναπαράσταση\". Για παράδειγμα \"Α: 41\". Πρέπει να τυπωθούν όλοι οι χαρακτήρες στο εύρος [0-127]. Στην θέση των χαρακτήρων [0x08-0x0d] θέλουμε να τυπώνεται το 'x'. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ gcc -o ascii ascii.c\n$ ./ascii 5\n\t:\t00 \t:\t19 \t2:\t32 \tK:\t4b \td:\t64 \t}:\t7d\n\t:\t01 \t�:\t1a \t3:\t33 \tL:\t4c \te:\t65 \t~:\t7e\n\t:\t02 \t\t1b \t4:\t34 \tM:\t4d \tf:\t66 \t:\t7f\n\t:\t03 \t:\t1c \t5:\t35 \tN:\t4e \tg:\t67\n\t:\t04 \t:\t1d \t6:\t36 \tO:\t4f \th:\t68\n\t:\t05 \t:\t1e \t7:\t37 \tP:\t50 \ti:\t69\n\t:\t06 \t:\t1f \t8:\t38 \tQ:\t51 \tj:\t6a\n\t:\t07 \t :\t20 \t9:\t39 \tR:\t52 \tk:\t6b\n\tx:\t08 \t!:\t21 \t::\t3a \tS:\t53 \tl:\t6c\n\tx:\t09 \t\":\t22 \t;:\t3b \tT:\t54 \tm:\t6d\n\tx:\t0a \t#:\t23 \t<:\t3c \tU:\t55 \tn:\t6e\n\tx:\t0b \t$:\t24 \t=:\t3d \tV:\t56 \to:\t6f\n\tx:\t0c \t%:\t25 \t>:\t3e \tW:\t57 \tp:\t70\n\tx:\t0d \t&:\t26 \t?:\t3f \tX:\t58 \tq:\t71\n\t:\t0e \t':\t27 \t@:\t40 \tY:\t59 \tr:\t72\n\t:\t0f \t(:\t28 \tA:\t41 \tZ:\t5a \ts:\t73\n\t:\t10 \t):\t29 \tB:\t42 \t[:\t5b \tt:\t74\n\t:\t11 \t*:\t2a \tC:\t43 \t\\:\t5c \tu:\t75\n\t:\t12 \t+:\t2b \tD:\t44 \t]:\t5d \tv:\t76\n\t:\t13 \t,:\t2c \tE:\t45 \t^:\t5e \tw:\t77\n\t:\t14 \t-:\t2d \tF:\t46 \t_:\t5f \tx:\t78\n\t:\t15 \t.:\t2e \tG:\t47 \t`:\t60 \ty:\t79\n\t:\t16 \t/:\t2f \tH:\t48 \ta:\t61 \tz:\t7a\n\t:\t17 \t0:\t30 \tI:\t49 \tb:\t62 \t{:\t7b\n\t:\t18 \t1:\t31 \tJ:\t4a \tc:\t63 \t|:\t7c\n$ ./ascii 6\n\t:\t00 \t:\t15 \t*:\t2a \t?:\t3f \tT:\t54 \ti:\t69 \t~:\t7e\n\t:\t01 \t:\t16 \t+:\t2b \t@:\t40 \tU:\t55 \tj:\t6a \t:\t7f\n\t:\t02 \t:\t17 \t,:\t2c \tA:\t41 \tV:\t56 \tk:\t6b\n\t:\t03 \t:\t18 \t-:\t2d \tB:\t42 \tW:\t57 \tl:\t6c\n\t:\t04 \t:\t19 \t.:\t2e \tC:\t43 \tX:\t58 \tm:\t6d\n\t:\t05 \t�:\t1a \t/:\t2f \tD:\t44 \tY:\t59 \tn:\t6e\n\t:\t06 \t\t1b \t0:\t30 \tE:\t45 \tZ:\t5a \to:\t6f\n\t:\t07 \t:\t1c \t1:\t31 \tF:\t46 \t[:\t5b \tp:\t70\n\tx:\t08 \t:\t1d \t2:\t32 \tG:\t47 \t\\:\t5c \tq:\t71\n\tx:\t09 \t:\t1e \t3:\t33 \tH:\t48 \t]:\t5d \tr:\t72\n\tx:\t0a \t:\t1f \t4:\t34 \tI:\t49 \t^:\t5e \ts:\t73\n\tx:\t0b \t :\t20 \t5:\t35 \tJ:\t4a \t_:\t5f \tt:\t74\n\tx:\t0c \t!:\t21 \t6:\t36 \tK:\t4b \t`:\t60 \tu:\t75\n\tx:\t0d \t\":\t22 \t7:\t37 \tL:\t4c \ta:\t61 \tv:\t76\n\t:\t0e \t#:\t23 \t8:\t38 \tM:\t4d \tb:\t62 \tw:\t77\n\t:\t0f \t$:\t24 \t9:\t39 \tN:\t4e \tc:\t63 \tx:\t78\n\t:\t10 \t%:\t25 \t::\t3a \tO:\t4f \td:\t64 \ty:\t79\n\t:\t11 \t&:\t26 \t;:\t3b \tP:\t50 \te:\t65 \tz:\t7a\n\t:\t12 \t':\t27 \t<:\t3c \tQ:\t51 \tf:\t66 \t{:\t7b\n\t:\t13 \t(:\t28 \t=:\t3d \tR:\t52 \tg:\t67 \t|:\t7c\n\t:\t14 \t):\t29 \t>:\t3e \tS:\t53 \th:\t68 \t}:\t7d\n```",
  "hint": "Οι χαρακτήρες τυπώνονται κατά στήλες, αλλά το τερματικό γράφει κατά γραμμές: για τη γραμμή r και τη στήλη c ο χαρακτήρας είναι `c * rows + r`. Βρείτε από τα παραδείγματα πώς προκύπτει το πλήθος γραμμών από το όρισμα και προσέξτε την ημιτελή τελευταία στήλη και τη μορφοποίηση με `%02x`."
 },
 {
  "id": "exam-2023-fall-ex15-q3",
  "kind": "exam",
  "title": "Ταξινομώντας τα Άλματα",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #15, Θέμα 3",
   "url": "https://progintro.github.io/exams/2023/fall/ex15/",
   "years": [
    2023
   ]
  },
  "chapters": [
   18,
   19,
   17
  ],
  "topics": [
   "files",
   "structs",
   "sorting",
   "strings"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α18.21",
  "path": "questions/exams/exam-2023-fall-ex15-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex15-q3.html",
  "statement": "Πρόγραμμα: `longjump.c`\n\nΓράψτε ένα πρόγραμμα το οποίο παίρνει ως όρισμα ένα αρχείο με τα άλματα που έκανε κάθε αθλητής και εκτυπώνει τους αθλητές σε φθίνουσα σειρά με βάση τα άλματα που έκαναν. Το αρχείο θα είναι σε μορφή JSON, δηλαδή θα αρχίζει με τον χαρακτήρα '{' και θα τελειώνει με τον χαρακτήρα '}' και για κάθε όνομα αθλητή θα τυπώνει `\"όνομα\": μήκος` όπου το μήκος θα είναι ένας αριθμός κινητής υποδιαστολής. Ανάμεσα σε κάθε αθλητή-άλμα θα υπάρχει ο χαρακτήρας ','. Δεν επιτρέπεται χρήση εξωτερικών βιβλιοθηκών. Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ cat jumps.json\n{\n    \"mcleod\": 8.20,\n    \"furlani\": 8.21,\n    \"montler\": 7.80,\n    \"batz\": 8.06,\n    \"williams\": 7.83,\n    \"lawson\": 8.05,\n    \"gayle\": 7.89,\n    \"tentoglou\": 8.22\n}\n$ gcc -o longjump longjump.c\n$ ./longjump jumps.json\ntentoglou: 8.22\nfurlani: 8.21\nmcleod: 8.20\nbatz: 8.06\nlawson: 8.05\ngayle: 7.89\nwilliams: 7.83\nmontler: 7.80\n```",
  "hint": "Διαβάστε το αρχείο χαρακτήρα-χαρακτήρα ή με `fscanf` και αναλύστε το: `{`, μετά ζεύγη `\"όνομα\": αριθμός` χωρισμένα με `,`, και `}`. Κρατήστε κάθε αθλητή σε `struct` και ταξινομήστε φθίνουσα με `qsort`. Αρχείο που δεν ακολουθεί τη μορφή είναι είσοδος εκτός προδιαγραφών."
 },
 {
  "id": "exam-2023-fall-ex15-q4",
  "kind": "exam",
  "title": "Δυνατότητες",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #15, Θέμα 4",
   "url": "https://progintro.github.io/exams/2023/fall/ex15/",
   "years": [
    2023
   ]
  },
  "chapters": [
   14,
   18
  ],
  "topics": [
   "strings",
   "files",
   "command-line-args"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α14.17",
  "path": "questions/exams/exam-2023-fall-ex15-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex15-q4.html",
  "statement": "Πρόγραμμα: `phone.c`\n\nΣε κάποια τηλέφωνα, ίσως έχετε παρατηρήσει πως ο κάθε αριθμός αντιστοιχεί σε συγκεκριμένα γράμματα:\n\n```text\n1       2 ABC   3 DEF\n4 GHI   5 JKL   6 MNO\n7 PQRS  8 TUV   9 WXYZ\n*       0       #\n```\n\n> Σημείωση: στο πρωτότυπο το πληκτρολόγιο δίνεται ως εικόνα ([phone.jpeg](https://progintro.github.io/exams/2023/fall/ex15/images/phone.jpeg)).\n\n(2 -> ABC, 3 -> DEF, ... κοκ). Λέγοντας έναν αριθμό, μπορείς να περιγράψεις ένα σύνολο από λέξεις και το αντίστροφο: μια λέξη προσδιορίζει έναν συγκεκριμένο αριθμό. Για παράδειγμα, η λέξη CAT προσδιορίζει το 228 (C -> 2, A -> 2, T -> 8). Γράψτε ένα πρόγραμμα, το οποίο παίρνει ως πρώτο όρισμα ένα αρχείο με λέξεις (μία ανά γραμμή) και έναν αριθμό ως το δεύτερο όρισμα και τυπώνει όλες τις λέξεις που μπορούν να εκφραστούν με αυτόν τον αριθμό. Οποιοδήποτε ψηφίο δεν ταιριάζει σε κάποιο γράμμα (0, 1) θεωρείται \"μπαλαντέρ\", δηλαδή ταιριάζει με οποιοδήποτε γράμμα. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ gcc -o phone phone.c\n$ ./phone words.txt\nUsage: ./phone dictionary phone\n$ cat words.txt\ncat\ndog\ndeep\npurple\nsmoke\nwater\nrain\nspain\nplain\n$ ./phone words.txt 228\ncat\n$ ./phone words.txt 70000\nsmoke\nspain\nplain\n$ ./phone words.txt 71246\nspain\nplain\n$ ./phone /usr/share/dict/words 71246\nRabin\nRobin\nRubin\nSabin\nSpahn\nSpain\nplain\nrobin\nslain\nstain\nswain\n```",
  "hint": "Φτιάξτε έναν πίνακα 26 θέσεων που αντιστοιχίζει κάθε γράμμα σε ψηφίο. Για κάθε λέξη του λεξικού ίδιου μήκους με τον αριθμό, συγκρίνετε θέση-θέση χωρίς διάκριση πεζών-κεφαλαίων, με τα 0 και 1 να ταιριάζουν με οτιδήποτε. Προσέξτε λέξεις με μη λατινικούς χαρακτήρες και το `'\\n'` στο τέλος κάθε γραμμής."
 },
 {
  "id": "exam-2023-fall-ex2-q1",
  "kind": "exam",
  "title": "Pikaκίστικα",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #2 (Pokémon Themed), Θέμα 1",
   "url": "https://progintro.github.io/exams/2023/fall/ex2/",
   "years": [
    2023
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α9.28",
  "path": "questions/exams/exam-2023-fall-ex2-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex2-q1.html",
  "statement": "Πρόγραμμα: `pika.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα που διαβάζει το κείμενο που δίνεται από την πρότυπη είσοδο (stdin) και τυπώνει την κάθε λέξη χαρακτήρα στην πρότυπη έξοδο (stdout) με το πρόθεμα \"pika\". Οι λέξεις χωρίζονται με κενούς (whitespace) χαρακτήρες. Αριθμοί ή σημεία στίξης *δεν* θεωρούνται λέξεις. Παράδειγμα εκτέλεσης:\n\n```text\n$ cat ash.txt\n\tI wanna be the very best�,\n\tLike no one ever was ,\n\tTo catch them is my real-test ,\n\tTo train them is my cause !\n$ ./pika  < ash.txt\n\tpikaI pikawanna pikabe pikathe pikavery pikabest�,\n\tpikaLike pikano pikaone pikaever pikawas ,\n\tpikaTo pikacatch pikathem pikais pikamy pikareal-test ,\n\tpikaTo pikatrain pikathem pikais pikamy pikacause !\n```",
  "hint": "Δεν χρειάζεται να αποθηκεύσετε ολόκληρες λέξεις: διαβάστε χαρακτήρα προς χαρακτήρα και κρατήστε μια μεταβλητή κατάστασης «είμαι μέσα σε λέξη ή όχι». Το πρόθεμα μπαίνει τη στιγμή που ξεκινά μια λέξη, και τα κενά (μαζί με τα tabs) αντιγράφονται όπως είναι. Κοιτάξτε προσεκτικά στο παράδειγμα ποιος χαρακτήρας κάνει ένα token «λέξη» (π.χ. `real-test` και `best�,` αλλά όχι `,` ή `!`)."
 },
 {
  "id": "exam-2023-fall-ex2-q2",
  "kind": "exam",
  "title": "Τουρνουά",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #2 (Pokémon Themed), Θέμα 2",
   "url": "https://progintro.github.io/exams/2023/fall/ex2/",
   "years": [
    2023
   ]
  },
  "chapters": [
   12,
   8
  ],
  "topics": [
   "command-line-args",
   "loops",
   "strings"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α12.14",
  "path": "questions/exams/exam-2023-fall-ex2-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex2-q2.html",
  "statement": "Πρόγραμμα: `tournament.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα που δέχεται ως ορίσματα όλα τα pokémon που διαγωνίζονται στο τουρνουά και στην συνέχεια τυπώνει στην πρότυπη έξοδο όλους τους αγώνες που θα γίνουν. Κάθε pokémon πρέπει να παίξει με κάθε άλλο ακριβώς δύο φορές. Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ ./tournament charmander dratini mew\ncharmander vs dratini\ncharmander vs mew\ndratini vs charmander\ndratini vs mew\nmew vs charmander\nmew vs dratini\n```",
  "hint": "Δύο εμφωλευμένοι βρόχοι πάνω στο `argv` αρκούν· σκεφτείτε ποιο ζεύγος δεικτών πρέπει να παραλείψετε ώστε κάθε ζευγάρι να παίζει ακριβώς δύο φορές (μία «εντός» και μία «εκτός»). Τι πρέπει να γίνει αν δοθούν λιγότερα από δύο pokémon ή το ίδιο όνομα δύο φορές;"
 },
 {
  "id": "exam-2023-fall-ex2-q3",
  "kind": "exam",
  "title": "Μίνι Βάση Δεδομένων",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #2 (Pokémon Themed), Θέμα 3",
   "url": "https://progintro.github.io/exams/2023/fall/ex2/",
   "years": [
    2023
   ]
  },
  "chapters": [
   18,
   19,
   13
  ],
  "topics": [
   "files",
   "structs",
   "sorting"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α18.22",
  "path": "questions/exams/exam-2023-fall-ex2-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex2-q3.html",
  "statement": "Πρόγραμμα: `pokedex.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα που παίρνει δύο ορίσματα: (1) το όνομα του αρχείο που περιέχει όλα τα pokémon που έχουμε πιάσει με όλα τα δεδομένα τους και (2) την ημερομηνία που αναζητούμε και επιστρέφει αναλυτικές πληροφορίες για όλα τα pokémon που πιάστηκαν *μετά* από εκείνη την ημερομηνία ταξινομημένα. Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ cat pokedex.db\nname, date_caught, level\ngeodude, 15-02-2024, 15\nslowpoke, 16-01-2024, 20\npidgeotto, 19-02-2024, 5\nbulbasaur, 01-01-2005, 37\nonix, 31-07-2021, 21\ngyarados, 20-12-2018, 19\n$ gcc -o pokedex pokedex.c\n$ ./pokedex pokedex.db 19-02-2024\npidgeotto was caught on 19-02-2024 and is level 5\n$ ./pokedex pokedex.db 01-01-2024\nslowpoke was caught on 16-01-2024 and is level 20\ngeodude was caught on 15-02-2024 and is level 15\npidgeotto was caught on 19-02-2024 and is level 5\n```",
  "hint": "Παραλείψτε τη γραμμή-επικεφαλίδα, διαβάστε κάθε εγγραφή σε ένα `struct` με `fgets` και `sscanf`, και μετατρέψτε την ημερομηνία `ΗΗ-ΜΜ-ΕΕΕΕ` σε έναν ακέραιο που συγκρίνεται σωστά (π.χ. έτος, μετά μήνας, μετά μέρα). Φιλτράρετε, ταξινομήστε κατά ημερομηνία με `qsort` και προσέξτε από το πρώτο παράδειγμα αν η ημερομηνία αναζήτησης περιλαμβάνεται. Επικυρώστε την ημερομηνία του ορίσματος (μορφή και εύρος μήνα/ημέρας)."
 },
 {
  "id": "exam-2023-fall-ex2-q4",
  "kind": "exam",
  "title": "Ανεβαίνοντας Επίπεδο",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #2 (Pokémon Themed), Θέμα 4",
   "url": "https://progintro.github.io/exams/2023/fall/ex2/",
   "years": [
    2023
   ]
  },
  "chapters": [
   25,
   16,
   11
  ],
  "topics": [
   "dynamic-programming",
   "recursion",
   "complexity",
   "integer-representation"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α25.7",
  "path": "questions/exams/exam-2023-fall-ex2-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex2-q4.html",
  "statement": "Πρόγραμμα: `levelup.c` (25 μονάδες)\n\nΈνα pokémon μπορεί να ανέβει 1, 2 ή 3 επίπεδα σε κάθε αγώνα ανάλογα με το πόσο δύσκολος είναι ο αντίπαλος (εύκολος, μεσαίος, δύσκολος). Γράψτε ένα πρόγραμμα που παίρνει ένα επίπεδο \"στόχο\" ως όρισμα και τυπώνει στην πρότυπη έξοδο με πόσους διαφορετικούς τρόπους μπορεί να φτάσει σε αυτό.  Έστω ότι θέλουμε να φτάσουμε στο επίπεδο 5. Ένας τρόπος να φτάσουμε είναι 1-1-1-1-1, δηλαδή να κερδίσουμε 5 εύκολους αντιπάλους. Ένας άλλος είναι ο 2-2-1 (δύο μεσαίους και μετά έναν εύκολο). Άλλοι πιθανοί τρόποι είναι οι 3-2, 2-3, 3-1-1, κ.ο.κ - σε κάθε περίπτωση θέλουμε να φτάσουμε *ακριβώς* στο επίπεδο στόχο. Παραδείγματα εκτελέσεων ακολουθούν:\n\n```text\n$ gcc -o levelup.c levelup\n$ ./levelup 3\nThere are 4 different ways to reach level 3\n$ ./levelup 5\nThere are 13 different ways to reach level 5\n$ ./levelup 6\nThere are 24 different ways to reach level 6\n$ ./levelup 50\nThere are 10562230626642 different ways to reach level 50\n```",
  "hint": "Σκεφτείτε αναδρομικά: με πόσους τρόπους φτάνω στο `n` αν ο τελευταίος αγώνας μού έδωσε 1, 2 ή 3 επίπεδα; Η απλή αναδρομή όμως ξαναϋπολογίζει τα ίδια υποπροβλήματα εκθετικά πολλές φορές και δεν θα τελειώσει για `n = 50`· αποθηκεύστε τα ενδιάμεσα αποτελέσματα ή υπολογίστε από κάτω προς τα πάνω. Το αποτέλεσμα ξεπερνά τον `int`, και οι αρχικές τιμές (τα `n` 1, 2, 3 ή 0) θέλουν προσοχή."
 },
 {
  "id": "exam-2023-fall-ex3-q1",
  "kind": "exam",
  "title": "Προσθήκη Νιφάδων",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #3 (Frozen Themed), Θέμα 1",
   "url": "https://progintro.github.io/exams/2023/fall/ex3/",
   "years": [
    2023
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α9.29",
  "path": "questions/exams/exam-2023-fall-ex3-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex3-q1.html",
  "statement": "Πρόγραμμα: `snow.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα που διαβάζει το κείμενο που δίνεται από την πρότυπη είσοδο (stdin) και τυπώνει την κάθε λέξη χαρακτήρα στην πρότυπη έξοδο (stdout) εμπλουτισμένη με νιφάδες, δηλαδή με τον χαρακτήρα `*`. Νιφάδες μπαίνουν μόνο ανάμεσα στα γράμματα της κάθε λέξης. Λέξεις με μόνο ένα γράμμα δεν χρειάζονται κάποια προσθήκη. Οι λέξεις αποτελούνται από τα γράμματα A-Z και a-z. Αριθμοί ή σημεία στίξης *δεν* θεωρούνται λέξεις. Παράδειγμα εκτέλεσης:\n\n```text\n$ cat elsa.txt\n\tLet it go, let it go�,\n\tTurn away and slam the door ,\n\tI don't care what they're going to say ,\n\tLet the storm rage on ,\n\tThe cold never bothered me anyway !\n$ gcc -o snow snow.c\n$ ./snow < elsa.txt\n\tL*e*t i*t g*o, l*e*t i*t g*o�,\n\tT*u*r*n a*w*a*y a*n*d s*l*a*m t*h*e d*o*o*r ,\n\tI d*o*n't c*a*r*e w*h*a*t t*h*e*y'r*e g*o*i*n*g t*o s*a*y ,\n\tL*e*t t*h*e s*t*o*r*m r*a*g*e o*n ,\n\tT*h*e c*o*l*d n*e*v*e*r b*o*t*h*e*r*e*d m*e a*n*y*w*a*y !\n```",
  "hint": "Διαβάστε χαρακτήρα προς χαρακτήρα και θυμηθείτε μόνο αν ο προηγούμενος χαρακτήρας ήταν γράμμα: η νιφάδα μπαίνει ακριβώς όταν δύο γράμματα είναι διαδοχικά. Κοιτάξτε στο παράδειγμα τι συμβαίνει στο `don't` και στο `they're`. Προσέξτε ότι η `isalpha` εξαρτάται από το locale, ενώ η εκφώνηση ορίζει ρητά A-Z και a-z."
 },
 {
  "id": "exam-2023-fall-ex3-q2",
  "kind": "exam",
  "title": "Φορτωμένο Έλκηθρο",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #3 (Frozen Themed), Θέμα 2",
   "url": "https://progintro.github.io/exams/2023/fall/ex3/",
   "years": [
    2023
   ]
  },
  "chapters": [
   10,
   12
  ],
  "topics": [
   "arrays",
   "loops",
   "command-line-args",
   "input-validation"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α10.21",
  "path": "questions/exams/exam-2023-fall-ex3-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex3-q2.html",
  "statement": "Πρόγραμμα: `sled.c` (25 μονάδες)\n\nO Kristoff θέλει να πάρει τρία αντικείμενα μαζί του και να ελέγξει αν γεμίζουν πλήρως (από πλευράς βάρους) το έλκηθρό του. Γράψτε ένα πρόγραμμα που δέχεται ως πρώτο όρισμα την χωρητικότητα του ελκήθρου και στην συνέχεια το βάρος του κάθε αντικειμένου που θα μπορούσε να πάρει. Περιορισμοί: (1) τα βάρη είναι όλα ακέραιοι, (2) πρέπει να πάρει αναγκαστικά 3 αντικείμενα, (3) το κάθε αντικείμενο έχει μοναδικό βάρος και (4) τα βάρη πρέπει να γεμίζουν *πλήρως* το έλκηθρο. Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ ./sled 42 18 1 4 81 47 35 22 41 2 3 17\nYou can take 3 objects: 18 + 22 + 2 = 42\nYou can take 3 objects: 4 + 35 + 3 = 42\nYou can take 3 objects: 22 + 3 + 17 = 42\n$ ./sled 42 18 1 4 81 47 35 41 2 17\nNo 3 objects found to fill up your sled.\n```",
  "hint": "Μετατρέψτε τα ορίσματα σε πίνακα ακεραίων (με έλεγχο ότι είναι έγκυροι ακέραιοι και ότι δεν επαναλαμβάνονται) και δοκιμάστε κάθε τριάδα δεικτών `i < j < k`, ώστε κάθε συνδυασμός να τυπωθεί μία φορά. Η σειρά εξόδου του παραδείγματος προκύπτει ακριβώς από αυτή τη σειρά απαρίθμησης. Αν θέλετε κάτι ταχύτερο από O(n³), σκεφτείτε ταξινόμηση και δύο δείκτες, αλλά τότε αλλάζει η σειρά εξόδου."
 },
 {
  "id": "exam-2023-fall-ex3-q3",
  "kind": "exam",
  "title": "Εύρεση Λέξεων",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #3 (Frozen Themed), Θέμα 3",
   "url": "https://progintro.github.io/exams/2023/fall/ex3/",
   "years": [
    2023
   ]
  },
  "chapters": [
   14,
   18
  ],
  "topics": [
   "strings",
   "files"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α14.18",
  "path": "questions/exams/exam-2023-fall-ex3-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex3-q3.html",
  "statement": "Πρόγραμμα: `find.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα που παίρνει δύο ορίσματα: (1) το όνομα του αρχείου που περιέχει το σύνολο των λέξεων που έχουμε διαθέσιμες και (2) την υπακολουθία που ψάχνουμε μέσα σε αυτές τις λέξεις. Το πρόγραμμά μας πρέπει να τυπώνει όσες λέξεις περιέχουν την υπακολουθία  (για παράδειγμα το \"snow\" περιέχεται στο \"snowman\" αλλά δεν περιέχεται στο \"noman\") και το μέρος που ταιριάζει στην υπακολουθία πρέπει να τονιστεί με **bold** χαρακτήρες. Προσοχή: μια υπακολουθία μπορεί να υπάρχει περισσότερες από μία φορές σε μια λέξη. Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ cat test.txt\nAnna\nArendelle\nSven\nHans\nIce\nSnow\n$ gcc -o find find.c\n$ ./find test.txt e\nArendelle\nSven\nIce\n$ ./find /usr/share/dict/words snowm\nsnowman\nsnowman's\nsnowmen\nsnowmobile\nsnowmobile's\nsnowmobiled\nsnowmobiles\nsnowmobiling\n```\n\n> Σημείωση: στο πρωτότυπο το παράδειγμα είναι στιγμιότυπο τερματικού ([εικόνα](https://progintro.github.io/exams/2023/fall/ex3/images/find.png)), όπου τα τμήματα που ταιριάζουν (όλα τα `e` στο `Arendelle`, `Sven`, `Ice` και το `snowm` στις υπόλοιπες) εμφανίζονται με έντονους χαρακτήρες.",
  "hint": "Διαβάστε το αρχείο γραμμή-γραμμή με `fgets` (αφαιρώντας το `'\\n'`) και σε κάθε λέξη ψάξτε όλες τις εμφανίσεις της υπακολουθίας, π.χ. με επαναλαμβανόμενες κλήσεις της `strstr` που συνεχίζουν μετά το προηγούμενο ταίριασμα. Τυπώστε τα κομμάτια ανάμεσα στα ταιριάσματα κανονικά και τα ταιριάσματα ανάμεσα στις ANSI escape sequences για bold και επαναφορά. Σκεφτείτε τι σημαίνει κενή υπακολουθία και τι γίνεται με επικαλυπτόμενα ταιριάσματα (π.χ. `aa` μέσα στο `aaa`)."
 },
 {
  "id": "exam-2023-fall-ex3-q4",
  "kind": "exam",
  "title": "Χτίζοντας έναν Χιονάνθρωπο",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #3 (Frozen Themed), Θέμα 4",
   "url": "https://progintro.github.io/exams/2023/fall/ex3/",
   "years": [
    2023
   ]
  },
  "chapters": [
   16,
   17,
   18
  ],
  "topics": [
   "problem-solving",
   "complexity",
   "sorting",
   "files"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α16.25",
  "path": "questions/exams/exam-2023-fall-ex3-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex3-q4.html",
  "statement": "Πρόγραμμα: `olaf.c` (25 μονάδες)\n\nΒρισκόμαστε σε έναν χιονισμένο τετράγωνο κήπο διαστάσεων ΝxN και Θέλουμε να φτιάξουμε έναν χιονάνθρωπο. Δυστυχώς το χιόνι είναι μαζεμένο σε συγκεκριμένους σωρούς μέσα στον κήπο (δεν είναι παντού). Γράψτε ένα πρόγραμμα που αποφασίζει που πρέπει να φτιάξουμε τον χιονάνθρωπό μας ώστε να κάνουμε τον ελάχιστο δυνατό κόπο. Για λόγους απλοποίησης θεωρούμε ότι όλες οι συντεταγμένες στον κήπο είναι ακέραιοι και ότι οι κινήσεις μας μπορούν να είναι μόνο πάνω-κάτω-αριστερά-δεξιά (όχι διαγώνια). Το μέγεθος του κήπου και οι τοποθεσίες των σωρών χιονιού δίνονται στο πρόγραμμα μέσω αρχείου του οποίου το όνομα θα είναι το πρώτο όρισμα του προγράμματος. Το αρχείο θα περιέχει την διάσταση του κήπου (Ν) ακολουθούμενη από τις συντεταγμένες του κάθε σωρού. Παράδειγμα επιτυχούς εκτέλεσης ακολουθεί:\n\n```text\n$ gcc -o olaf olaf.c\n$ cat map.txt\n10\n1 1\n6 7\n2 8\n7 2\n$ ./olaf map.txt\nWe will position the snowman on (4, 4) with a minimum cost of 22.\n```\n\nΠαρακάτω βλέπουμε την οπτικοποίηση της επιλογής μας - ο χιονάνθρωπος βρίσκεται στην θέση \"καρότο\" ενώ οι σωροί με τα χιόνια απεικονίζονται με τους κύκλους. Από τους δύο πάνω σωρούς παρατηρούμε ότι χρειαζόμαστε 6 βήματα για να φτάσουμε τον χιονάνθρωπο ενώ από τους δύο κάτω χρειαζόμαστε 5 - σύνολο (6 + 6 + 5 + 5 =) 22. Παρατηρήστε ότι μπορεί να υπάρχουν πάνω από μία βέλτιστες τοποθετήσεις, χρειάζεται να βρούμε μόνο μία από αυτές. Για λόγους απλότητας ο χιονάνθρωπος μπορεί να τοποθετηθεί πάνω σε έναν σωρό (και τα βήματα που απαιτούνται σε αυτήν την περίπτωση είναι 0).\n\n![path to the snowman](https://progintro.github.io/exams/2023/fall/ex3/images/map.png)",
  "hint": "Το κόστος μιας θέσης είναι το άθροισμα των αποστάσεων Manhattan `|x - xi| + |y - yi|` από όλους τους σωρούς. Μια λύση ωμής βίας δοκιμάζει κάθε κελί του κήπου, αλλά κοστίζει O(N²·K)· παρατηρήστε ότι οι δύο συντεταγμένες ανεξαρτητοποιούνται και ρωτήστε τον εαυτό σας ποιο σημείο ελαχιστοποιεί το άθροισμα απολύτων αποστάσεων σε μία διάσταση. Ελέγξτε ότι οι συντεταγμένες είναι μέσα στον κήπο και ότι υπάρχει τουλάχιστον ένας σωρός."
 },
 {
  "id": "exam-2023-fall-ex4-q1",
  "kind": "exam",
  "title": "Αναγράμματα",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #4 (Rick Astley Themed), Θέμα 1",
   "url": "https://progintro.github.io/exams/2023/fall/ex4/",
   "years": [
    2023
   ]
  },
  "chapters": [
   10,
   14
  ],
  "topics": [
   "arrays",
   "strings",
   "command-line-args"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α10.22",
  "path": "questions/exams/exam-2023-fall-ex4-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex4-q1.html",
  "statement": "Πρόγραμμα: `anagram.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα που δέχεται δύο ορίσματα και ελέγχει αν το ένα είναι ένα ανάγραμμα του άλλου. Δύο φράσεις λέγονται αναγράμματα όταν περιέχουν τους ίδιους χαρακτήρες αλλά πιθανώς με διαφορετική σειρά π.χ., οι φράσεις \"desert you\" και \"you rested\" είναι αναγράμματα η μία της άλλης. Παράδειγμα εκτέλεσης:\n\n```text\n$ gcc -o anagram anagram.c\n$ ./anagram \"desert you!\" \"you rested!\"\n\"desert you!\" is an anagram of \"you rested!\".\n$ ./anagram \"never gonna give\" \"never gonna give\"\n\"never gonna give\" is an anagram of \"never gonna give\".\n$ ./anagram \"never gonna give\" \"gonna run around\"\n\"never gonna give\" is NOT an anagram of \"gonna run around\".\n```",
  "hint": "Μετρήστε πόσες φορές εμφανίζεται κάθε χαρακτήρας σε κάθε φράση, με έναν πίνακα 256 μετρητών που δεικτοδοτείται από την τιμή του byte (ως `unsigned char`), και συγκρίνετε τα δύο ιστογράμματα. Αυτό είναι O(n), σε αντίθεση με την ταξινόμηση ή τη σύγκριση όλων με όλους. Ελέγξτε ότι δόθηκαν ακριβώς δύο ορίσματα."
 },
 {
  "id": "exam-2023-fall-ex4-q2",
  "kind": "exam",
  "title": "Τα Πάνω Κάτω",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #4 (Rick Astley Themed), Θέμα 2",
   "url": "https://progintro.github.io/exams/2023/fall/ex4/",
   "years": [
    2023
   ]
  },
  "chapters": [
   14,
   9
  ],
  "topics": [
   "strings",
   "input-output"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α14.19",
  "path": "questions/exams/exam-2023-fall-ex4-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex4-q2.html",
  "statement": "Πρόγραμμα: `updown.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα που διαβάζει το κείμενο που δίνεται από την πρότυπη είσοδο (stdin) και τυπώνει την κάθε λέξη χαρακτήρα στην πρότυπη έξοδο (stdout) έχοντας κάνει την εξής αντικατάσταση: κάθε λέξη \"up\" πρέπει να αντικατασταθεί με την λέξη \"down\" και κάθε \"down\" πρέπει να αντικατασταθεί με την λέξη \"up\". Οι λέξεις χωρίζονται με κενά (whitespace). Η αντικατάσταση πρέπει να γίνεται σε ολόκληρες λέξεις, όχι μέρος τους. Παράδειγμα εκτέλεσης:\n\n```text\n$ cat rick.txt\nupload and download this �:\nnever gonna give you up ,\nnever gonna let you down ,\nnever gonna run around and desert you !\n$ gcc -o updown updown.c\n$ ./updown < rick.txt\nupload and download this �:\nnever gonna give you down ,\nnever gonna let you up ,\nnever gonna run around and desert you !\n```",
  "hint": "Συγκεντρώστε κάθε λέξη (μέγιστη ακολουθία χαρακτήρων που δεν είναι whitespace) σε έναν buffer και, μόλις τελειώσει, συγκρίνετέ την με `strcmp` με τα `\"up\"` και `\"down\"` πριν την τυπώσετε· τα whitespace αντιγράφονται αυτούσια. Προσοχή στις πολύ μεγάλες λέξεις (δεν χωράνε σε σταθερό buffer, αλλά αρκεί να ξέρετε ότι δεν είναι ούτε `up` ούτε `down`) και στην τελευταία λέξη όταν το αρχείο δεν τελειώνει σε αλλαγή γραμμής."
 },
 {
  "id": "exam-2023-fall-ex4-q3",
  "kind": "exam",
  "title": "Rickroll Τριπλέτες",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #4 (Rick Astley Themed), Θέμα 3",
   "url": "https://progintro.github.io/exams/2023/fall/ex4/",
   "years": [
    2023
   ]
  },
  "chapters": [
   2,
   5
  ],
  "topics": [
   "integer-representation",
   "bitwise",
   "loops"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α2.12",
  "path": "questions/exams/exam-2023-fall-ex4-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex4-q3.html",
  "statement": "Πρόγραμμα: `roll.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα που παίρνει 3 αριθμούς ως ορίσματα (σε αναπαράσταση μη προσημασμένου 32-bit αριθμού) και ελέγχει αν είναι είναι μια rickroll τριπλέτα. Τρεις αριθμοί a, b και c λέγονται rickroll τριπλέτα εάν υπάρχουν ακέραιοι I, J, K (διαφορετικοί ο ένας από τον άλλον I <> J <> K) έτσι ώστε 2^I * a + 2^J * b = 2^K * c - όπου όλες οι πράξεις είναι μη προσημασμένες mod 2^32. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ gcc -o roll roll.c\n$ ./roll 17 42 101\nFound rick-roll triplet: 2^30 * 17 + 2^25 * 42 = 2^26 * 101 = 2483027968\nFound rick-roll triplet: 2^30 * 17 + 2^29 * 42 = 2^31 * 101 = 2147483648\nFound rick-roll triplet: 2^31 * 17 + 2^26 * 42 = 2^27 * 101 = 671088640\n$ ./roll 17 42 100\nFound rick-roll triplet: 2^27 * 17 + 2^29 * 42 = 2^25 * 100 = 3355443200\nFound rick-roll triplet: 2^28 * 17 + 2^25 * 42 = 2^24 * 100 = 1677721600\nFound rick-roll triplet: 2^28 * 17 + 2^30 * 42 = 2^26 * 100 = 2415919104\nFound rick-roll triplet: 2^29 * 17 + 2^26 * 42 = 2^25 * 100 = 3355443200\nFound rick-roll triplet: 2^29 * 17 + 2^31 * 42 = 2^27 * 100 = 536870912\nFound rick-roll triplet: 2^30 * 17 + 2^27 * 42 = 2^26 * 100 = 2415919104\nFound rick-roll triplet: 2^30 * 17 + 2^31 * 42 = 2^28 * 100 = 1073741824\nFound rick-roll triplet: 2^31 * 17 + 2^28 * 42 = 2^27 * 100 = 536870912\n$ ./roll 3 5 7\nNo rick-roll triplets found.\n$ ./roll 0 0 1\nNo rick-roll triplets found.\n```",
  "hint": "Πολλαπλασιασμός με 2^I είναι αριστερή ολίσθηση κατά I, και σε μη προσημασμένο 32-bit τύπο (`uint32_t`) η αναδίπλωση mod 2^32 γίνεται αυτόματα, οπότε μια εξαντλητική αναζήτηση στα I, J, K είναι αρκετά μικρή. Σκεφτείτε ποιο είναι το λογικό εύρος των εκθετών (τι παθαίνει μια ολίσθηση κατά 32 ή περισσότερα bits;) και ποια σειρά βρόχων δίνει τη σειρά εξόδου του παραδείγματος. Διαβάστε τα ορίσματα με `strtoul` και απορρίψτε ό,τι δεν χωράει σε 32 bits."
 },
 {
  "id": "exam-2023-fall-ex4-q4",
  "kind": "exam",
  "title": "Αλλαγή Μεγέθους",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #4 (Rick Astley Themed), Θέμα 4",
   "url": "https://progintro.github.io/exams/2023/fall/ex4/",
   "years": [
    2023
   ]
  },
  "chapters": [
   18,
   12
  ],
  "topics": [
   "files",
   "bitwise",
   "command-line-args"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α18.17",
  "path": "questions/exams/exam-2023-fall-ex4-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex4-q4.html",
  "statement": "Πρόγραμμα: `crop.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα το οποίο παίρνει 3 ορίσματα: (1) το όνομα ενός αρχείου, (2) την τοποθεσία (offset) σε αριθμό bytes μέσα στο αρχείο και (3) έναν αριθμό των δύο bytes (short) και τυπώνει στην πρότυπη έξοδο (stdout) το περιεχόμενο του αρχείου με τα δύο bytes στην τοποθεσία που αναφέρθηκε να έχουν αντικατασταθεί από τα bytes του αριθμού που δόθηκε από την γραμμή εντολών (όρισμα 3). Το υπόλοιπο αρχείο δεν πρέπει να αλλαχθεί. Τα αρχεία που θα δοθούν θα είναι μέχρι 100ΜΒ. Η εκτέλεση `./crop file 2 13362` σημαίνει διάβασε το αρχείο `file` και στο byte στην θέση `2` τοποθέτησε τα δύο bytes του αριθμού `13362`. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ gcc -o crop crop.c\n$ echo example > file\n$ hexdump -C file\n00000000  65 78 61 6d 70 6c 65 0a                           |example.|\n00000008\n$ ./crop file 2 13362 > file2\n$ hexdump -C file2\n00000000  65 78 34 32 70 6c 65 0a                           |ex42ple.|\n00000008\n$ file rick.jpg\nrick.jpg: JPEG image data, JFIF standard 1.01, resolution (DPI), density 96x96, segment length 16, comment: \"CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), quality = 80\", baseline, precision 8, 640x436, components 3\n$ ./crop rick.jpg 224 218 > rick2.jpg\n$ file rick2.jpg\nrick2.jpg: JPEG image data, JFIF standard 1.01, resolution (DPI), density 96x96, segment length 16, comment: \"CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), quality = 80\", baseline, precision 8, 640x218, components 3\n```\n\nΠαρακάτω δείχνουμε το αποτέλεσμα της εκτέλεσης στην εικόνα [rick.jpg](https://progintro.github.io/exams/2023/fall/ex4/rick.jpg) (πριν):\n\n![rick before](https://progintro.github.io/exams/2023/fall/ex4/rick.jpg)\n\nΚαι μετά:\n\n![rick after](https://progintro.github.io/exams/2023/fall/ex4/images/rick2.jpg)",
  "hint": "Ανοίξτε το αρχείο σε δυαδική λειτουργία (`\"rb\"`) και αντιγράψτε το στην έξοδο byte προς byte ή σε μπλοκ, αντικαθιστώντας μόνο τα bytes στις θέσεις `offset` και `offset + 1`. Γράψτε το 13362 στο δεκαεξαδικό και συγκρίνετε με το hexdump για να δείτε με ποια σειρά μπαίνουν τα δύο bytes (endianness)· τα βγάζετε με ολισθήσεις και μάσκες, όχι με `memcpy` από ένα `short`. Ελέγξτε ότι ο αριθμός χωράει σε δύο bytes και ότι το offset δεν ξεπερνά το μέγεθος του αρχείου."
 },
 {
  "id": "exam-2023-fall-ex5-q1",
  "kind": "exam",
  "title": "Αναποδογύρισμα",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #5 (HP Themed), Θέμα 1",
   "url": "https://progintro.github.io/exams/2023/fall/ex5/",
   "years": [
    2023
   ]
  },
  "chapters": [
   10,
   9
  ],
  "topics": [
   "arrays",
   "input-output"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α10.18",
  "path": "questions/exams/exam-2023-fall-ex5-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex5-q1.html",
  "statement": "Πρόγραμμα: `flip.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα που διαβάζει το κείμενο που δίνεται από την πρότυπη είσοδο (stdin) και τυπώνει την κάθε γραμμή στην πρότυπη έξοδο (stdout) αντίστροφα, δηλαδή τυπώνοντας τους χαρακτήρες όπως θα διαβάζονταν από τα δεξιά προς τα αριστερά. Παράδειγμα εκτέλεσης:\n\n```text\n$ gcc -o flip flip.c\n$ cat riddle.txt\n, esiugsid ni sevil ohw nosrep eht fo kniht tsriF\n. seil tub thguan sllet dna sterces ni slaed ohW\n, dnem ot gniht tsal eht syawla s'tahw em llet ,txeN\n? dne eht fo dne dna elddim fo elddim ehT\n draeh netfo dnuos eht em evig yllanif dnA\n� drow dnif-ot-drah a rof hcraes eht gniruD\n, siht em rewsna dna ,rehtegot meht gnirts woN\n? ssik ot gnilliwnu eb uoy dluow erutaerc hcihW\n$ ./flip < riddle.txt\nFirst think of the person who lives in disguise ,\nWho deals in secrets and tells naught but lies .\nNext, tell me what's always the last thing to mend ,\nThe middle of middle and end of the end ?\nAnd finally give me the sound often heard\nDuring the search for a hard-to-find word �\nNow string them together, and answer me this ,\nWhich creature would you be unwilling to kiss ?\n```",
  "hint": "Μαζέψτε τους χαρακτήρες κάθε γραμμής σε έναν πίνακα μέχρι το `'\\n'` και τυπώστε τους από το τέλος προς την αρχή, αφήνοντας την αλλαγή γραμμής στη θέση της. Αν οι γραμμές μπορεί να είναι οσοδήποτε μεγάλες, ο πίνακας πρέπει να μεγαλώνει δυναμικά (`realloc`). Μην ξεχάσετε την τελευταία γραμμή χωρίς `'\\n'`."
 },
 {
  "id": "exam-2023-fall-ex5-q2",
  "kind": "exam",
  "title": "Μαγικό Ζευγάρι",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #5 (HP Themed), Θέμα 2",
   "url": "https://progintro.github.io/exams/2023/fall/ex5/",
   "years": [
    2023
   ]
  },
  "chapters": [
   10,
   12
  ],
  "topics": [
   "arrays",
   "command-line-args",
   "input-validation"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α10.23",
  "path": "questions/exams/exam-2023-fall-ex5-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex5-q2.html",
  "statement": "Πρόγραμμα: `magicpair.c` (25 μονάδες)\n\nΔύο θετικοί ακέραιοι αποτελούν μαγικό ζευγάρι εάν αποτελούνται από τα ίδια ψηφία αλλά πιθανόν με διαφορετική σειρά. Για παράδειγμα, οι αριθμοί 1980 και 1908 αποτελούν ένα μαγικό ζευγάρι, ενώ οι αριθμοί 1980 και 198 δεν είναι. Γράψτε ένα πρόγραμμα που δέχεται ακεραίους σε δεκαδική μορφή ως ορίσματα και τυπώνει αν οι αριθμοί αποτελούν ένα μαγικό ζευγάρι. Παραδείγματα εκτέλεσης:\n\n```text\n$ ./magicpair 1980 1908\n1980 and 1908 are a magic pair.\n$ ./magicpair 1980 198\nNot a magic pair\n$ ./magicpair -18 -18\nNot a magic pair\n$ ./magicpair 4321 1234\n4321 and 1234 are a magic pair.\n$ ./magicpair 4231444232 3244214243\n4231444232 and 3244214243 are a magic pair.\n```",
  "hint": "Μετρήστε πόσες φορές εμφανίζεται κάθε ψηφίο 0-9 σε κάθε αριθμό (ένας πίνακας 10 μετρητών ανά αριθμό) και συγκρίνετε. Τα παραδείγματα ξεπερνούν τον `int`, οπότε ή δουλέψτε με 64-bit ακέραιους ή απευθείας με τους χαρακτήρες του ορίσματος, αφού ελέγξετε ότι είναι μόνο ψηφία. Τι απαντάτε για αρνητικούς αριθμούς, για το 0 και για είσοδο που δεν είναι αριθμός;"
 },
 {
  "id": "exam-2023-fall-ex5-q3",
  "kind": "exam",
  "title": "Επιλογή",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #5 (HP Themed), Θέμα 3",
   "url": "https://progintro.github.io/exams/2023/fall/ex5/",
   "years": [
    2023
   ]
  },
  "chapters": [
   18,
   14
  ],
  "topics": [
   "files",
   "strings",
   "floating-point"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α18.18",
  "path": "questions/exams/exam-2023-fall-ex5-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex5-q3.html",
  "statement": "Πρόγραμμα: `sorting.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα το οποίο παίρνει ως όρισμα το όνομα ενός αρχείου που περιέχει ονόματα παιδιών και το σκορ ταιριάσματος του κάθε παιδιού με έναν κοιτώνα του Hogwarts. Κάθε γραμμή περιέχει ακριβώς ένα όνομα ακολουθούμενο από παύλα (dash -) και από το σκορ ταιριάσματος (ένας αριθμός κινητής υποδιαστολής από το 0 μέχρι το 5). Η αντιστοιχία έχει ως εξής: 1 -> Gryffindor, 2 -> Hufflepuff, 3 -> Ravenclaw, 4 -> Slytherin. Το πρόγραμμα πρέπει να τυπώνει στην πρότυπη έξοδο το κάθε όνομα ακολουθούμενο από το όνομα του κοιτώνα που ταιριάζει καλύτερα. Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ cat names.txt\nHarry Potter - 1.01\nHermione Granger - 1\nDraco Malfoy - 4.9\nCho Chang - 3.5\nCedric Diggory - 1.50001\nLuna Lovegood - 2.76\n$ gcc -o sorting sorting.c\n$ ./sorting names.txt\nHarry Potter -> Gryffindor\nHermione Granger -> Gryffindor\nDraco Malfoy -> Slytherin\nCho Chang -> Ravenclaw\nCedric Diggory -> Hufflepuff\nLuna Lovegood -> Ravenclaw\n```",
  "hint": "Διαβάστε το αρχείο γραμμή-γραμμή με `fgets` και χωρίστε όνομα και σκορ στην παύλα (το όνομα έχει κενά, οπότε η `strrchr` βοηθά), μετατρέποντας το σκορ με `strtod`. Ο «καλύτερος» κοιτώνας είναι ο πλησιέστερος στο σκορ: μελετήστε τα `4.9`, `3.5` και `1.50001` του παραδείγματος για να καταλάβετε τι γίνεται στα άκρα (0 και 5) και στις ισοπαλίες. Γραμμές χωρίς παύλα ή με σκορ εκτός [0, 5] είναι είσοδος εκτός προδιαγραφών."
 },
 {
  "id": "exam-2023-fall-ex5-q4",
  "kind": "exam",
  "title": "Μεταμορφώσιμες Προτάσεις",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #5 (HP Themed), Θέμα 4",
   "url": "https://progintro.github.io/exams/2023/fall/ex5/",
   "years": [
    2023
   ]
  },
  "chapters": [
   14,
   12
  ],
  "topics": [
   "strings",
   "command-line-args",
   "arrays"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α14.22",
  "path": "questions/exams/exam-2023-fall-ex5-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex5-q4.html",
  "statement": "Πρόγραμμα: `meta.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα που παίρνει 2 προτάσεις ως ορίσματα από την γραμμή εντολών και τυπώνει αν η μία πρόταση μπορεί να μεταμορφωθεί στην άλλη κάνοντας αντικαταστάσεις λέξεων καθώς και ποιες αντικαταστάσεις απαιτούνται. Για να μπορεί να μεταμορφωθεί μια πρόταση σε μια δεύτερη πρέπει *όλες* οι λέξεις της πρώτης να ταιριάξουν με λέξεις της δεύτερης μία προς μία. Οι προτάσεις θα έχουν μόνο κενά και λατινικούς χαρακτήρες (A-Z, a-z). Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ ./meta \"I solemnly swear I am up to no good\" \"Magic glimmers brightly Magic creatures stand under the moonlight\"\nYou can metamorphose the first sentence into the second sentence\nI <-> Magic\nsolemnly <-> glimmers\nswear <-> brightly\nam <-> creatures\nup <-> stand\nto <-> under\nno <-> the\ngood <-> moonlight\n$ ./meta \"I solemnly swear I am up to no good\" \"Magic glimmers brightly magic creatures stand under the moonlight\"\nYou cannot metamorphose the first sentence into the second sentence\n```",
  "hint": "Χωρίστε κάθε πρόταση σε πίνακα λέξεων και απαιτήστε ίδιο πλήθος λέξεων. Η αντιστοίχιση πρέπει να είναι ένα-προς-ένα και προς τις δύο κατευθύνσεις: η ίδια λέξη της πρώτης πρότασης πρέπει πάντα να πηγαίνει στην ίδια λέξη της δεύτερης, και δύο διαφορετικές λέξεις δεν μπορούν να πάνε στην ίδια. Προσέξτε ότι η σύγκριση κάνει διάκριση πεζών-κεφαλαίων (δεύτερο παράδειγμα) και ότι κάθε ζεύγος τυπώνεται μία φορά, με τη σειρά πρώτης εμφάνισης."
 },
 {
  "id": "exam-2023-fall-ex6-q1",
  "kind": "exam",
  "title": "Μέγιστος Κοινός Διαιρέτης",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #6 (Crypto Themed), Θέμα 1",
   "url": "https://progintro.github.io/exams/2023/fall/ex6/",
   "years": [
    2023
   ]
  },
  "chapters": [
   6,
   4,
   2
  ],
  "topics": [
   "math-algorithms",
   "command-line-args",
   "input-validation",
   "integer-representation"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α6.16",
  "path": "questions/exams/exam-2023-fall-ex6-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex6-q1.html",
  "statement": "Πρόγραμμα: `gcd.c` (25 μονάδες)\n\nΜέγιστος κοινός διαιρέτης ονομάζεται ο μεγαλύτερος ακέραιος που διαιρεί δύο ή περισσότερους ακέραιους αριθμούς. Για παράδειγμα ο μέγιστος κοινός διαιρέτης του 42 και του 27 είναι το 3 (καθώς διαιρεί ακριβώς και το 42/3=14 και το 27/3=9). Γράψτε ένα πρόγραμμα που διαβάζει δύο θετικούς ακεραίους σε δεκαδική μορφή από την γραμμή εντολών και τυπώνει τον μέγιστο κοινό διαιρέτη. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ gcc -o gcd gcd.c\n$ ./gcd 42 27\nGreatest common divisor of 42 and 27 is 3\n$ ./gcd 42 -27\nNumbers must be positive\n$ ./gcd 54 24\nGreatest common divisor of 54 and 24 is 6\n$ ./gcd 9827345 9182767\nGreatest common divisor of 9827345 and 9182767 is 11\n$ ./gcd 782936492674398272 982137984792892\nGreatest common divisor of 782936492674398272 and 982137984792892 is 4\n$ ./gcd 260056890954482 23809214813964\nGreatest common divisor of 260056890954482 and 23809214813964 is 2982734\n```",
  "hint": "Ο αλγόριθμος του Ευκλείδη (με υπόλοιπα, όχι με διαδοχικές αφαιρέσεις) τελειώνει σε λίγα βήματα ακόμα και για πολύ μεγάλους αριθμούς, ενώ η δοκιμή όλων των πιθανών διαιρετών όχι. Τα παραδείγματα χρειάζονται 64-bit ακέραιους: διαβάστε τα ορίσματα με `strtoll`/`strtoull` και ελέγξτε ότι είναι έγκυροι θετικοί αριθμοί που χωράνε στον τύπο."
 },
 {
  "id": "exam-2023-fall-ex6-q2",
  "kind": "exam",
  "title": "Μήνυμα από τον Καίσαρα",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #6 (Crypto Themed), Θέμα 2",
   "url": "https://progintro.github.io/exams/2023/fall/ex6/",
   "years": [
    2023
   ]
  },
  "chapters": [
   9,
   5
  ],
  "topics": [
   "input-output",
   "operators"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α9.23",
  "path": "questions/exams/exam-2023-fall-ex6-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex6-q2.html",
  "statement": "Πρόγραμμα: `caesar.c` (25 μονάδες)\n\nΥπάρχει ένας τρόπος κρυπτογράφησης που αποδίδεται στον Καίσαρα (Caesar Cipher) όπου κάθε γράμμα της αλφαβήτου αντιστοιχίζεται σε ένα άλλο. Για παράδειγμα με μετάθεση γραμμάτων κατά 3 παίρνουμε την ακόλουθη αντιστοίχιση:\n\n![Αντιστοίχιση γραμμάτων](https://progintro.github.io/exams/2023/fall/ex6/images/caesar.png)\n\nΌπου το A αντιστοιχεί στο Z, το D στο A, κοκ. Γράψτε ένα πρόγραμμα που διαβάζει το κείμενο που δίνεται από την πρότυπη είσοδο (stdin) και το τυπώνει στην πρότυπη έξοδο (stdout) αφού το περάσει από κρυπτογράφηση με την μέθοδο του Καίσαρα όπου η μετατόπιση είναι 13, δηλαδή το A αντιστοιχεί στο N, το B αντιστοιχεί στο O κοκ. Το πρόγραμμα πρέπει να αντικαθιστά μόνο λατινικούς χαρακτήρες (A-Z, a-z) και όλοι οι υπόλοιποι πρέπει να μένουν ίδιοι. Παράδειγμα εκτέλεσης:\n\n```text\n$ gcc -o caesar caesar.c\n$ cat toto.txt\nVg'f tbaan gnxr n ybg gb qent zr njnl sebz lbh� ,\nGurer'f abguvat gung n uhaqerq zra be zber pbhyq rire qb ,\nV oyrff gur envaf qbja va Nsevpn ,\nTbaan gnxr fbzr gvzr gb qb gur guvatf jr arire unq !\n$ ./caesar < toto.txt\nIt's gonna take a lot to drag me away from you� ,\nThere's nothing that a hundred men or more could ever do ,\nI bless the rains down in Africa ,\nGonna take some time to do the things we never had !\n```",
  "hint": "Διαβάστε χαρακτήρα προς χαρακτήρα· για κεφαλαία και πεζά ξεχωριστά, υπολογίστε τη θέση του γράμματος στο αλφάβητο (`c - 'A'`), προσθέστε τη μετατόπιση και κάντε αναδίπλωση με `%`. Όλοι οι άλλοι χαρακτήρες, ακόμη και bytes που δεν είναι έγκυρο κείμενο, περνάνε αυτούσιοι. Αφού το αλφάβητο έχει 26 γράμματα, τι παθαίνει ένα κείμενο αν του εφαρμόσετε ROT13 δύο φορές;"
 },
 {
  "id": "exam-2023-fall-ex6-q3",
  "kind": "exam",
  "title": "Σπάσε το PIN",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #6 (Crypto Themed), Θέμα 3",
   "url": "https://progintro.github.io/exams/2023/fall/ex6/",
   "years": [
    2023
   ]
  },
  "chapters": [
   14,
   8
  ],
  "topics": [
   "problem-solving",
   "strings",
   "loops"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α14.20",
  "path": "questions/exams/exam-2023-fall-ex6-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex6-q3.html",
  "statement": "Πρόγραμμα: `pin.c` (25 μονάδες)\n\nΤο αρχείο pin.c προσομοιάζει τον έλεγχο ενός συστήματος που ελέγχει αν το pin σου είναι σωστό και αν επιτρέπεται η πρόσβαση. Βρείτε το pin και προσθέστε το στο πρόγραμμα προκειμένου να τυπώσει \"Access granted\". Δεν επιτρέπεται να αλλάξετε τις ρουτίνες υπολογισμού της ορθότητας του pin αλλά μπορείτε να κάνετε όποιες άλλες δοκιμές / αλλαγές θέλετε. Γνωρίζουμε ότι ο pin είναι τετραψήφιος. Βεβαιωθείτε ότι καταγράψατε στο αρχείο όλον τον κώδικα που γράψατε για να βρείτε το pin. Παράδειγμα επιτυχούς εκτέλεσης ακολουθεί:\n\n```text\n$ gcc -o pin pin.c\n$ ./pin\nAccess granted\n```\n\nΤο αρχείο [pin.c](https://progintro.github.io/exams/2023/fall/ex6/pin.c):\n\n```c\n// Program that checks whether a pin is correct.\n\n#include <stdio.h>\n\n// Password converter routine, cannot be changed\nint converter(const char *str) {\n    int num = 5381;\n    int c;\n    while ((c = *str++)) {\n        num = ((num << 5) + num) + c;\n    }\n    return num;\n}\n\nint main() {\n\n    // Γνωρίζουμε ότι το πρώτο ψηφίο του pin είναι το 7,\n    // αλλά δεν γνωρίζουμε την συνέχεια. Αλλάξτε το pin προκειμένου\n    // να μπορέσουμε να πάρουμε πρόσβαση. Γράψτε όσον κώδικα χρειαστήκατε\n    // και όποιες μεθόδους χρησιμοποιήσατε για να το βρείτε σε αυτό το\n    // αρχείο. Μπορείτε να βάλετε εδώ το σωστό pin όταν το βρείτε.\n    char pin[] = \"7...\";\n\n\n\n    // Cannot change the checks below\n    if (converter(pin) == 2088511771) {\n        printf(\"Access granted\\n\");\n    } else {\n        printf(\"Access denied\\n\");\n    }\n\n    return 0;\n}\n```",
  "hint": "Η `converter` είναι μια συνάρτηση κατακερματισμού που δεν αντιστρέφεται εύκολα, αλλά οι υποψήφιοι τετραψήφιοι κωδικοί είναι ελάχιστοι: δοκιμάστε τους όλους (ωμή βία). Χρειάζεται να φτιάχνετε για κάθε υποψήφιο την αντίστοιχη συμβολοσειρά τεσσάρων ψηφίων (π.χ. με `sprintf` ή γεμίζοντας τις θέσεις του πίνακα με `'0' + ψηφίο`) και να κρατήσετε τον κώδικα αναζήτησης στο αρχείο, όπως ζητά η εκφώνηση."
 },
 {
  "id": "exam-2023-fall-ex6-q4",
  "kind": "exam",
  "title": "Ταξινόμηση Αρχείων Καταγραφής",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #6 (Crypto Themed), Θέμα 4",
   "url": "https://progintro.github.io/exams/2023/fall/ex6/",
   "years": [
    2023
   ]
  },
  "chapters": [
   18,
   13,
   14
  ],
  "topics": [
   "sorting",
   "files",
   "strings"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α18.19",
  "path": "questions/exams/exam-2023-fall-ex6-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex6-q4.html",
  "statement": "Πρόγραμμα: `sortlog.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα το οποίο παίρνει ως όρισμα το όνομα ενός αρχείου που περιέχει δεδομένα από αρχεία καταγραφής (logs) και τυπώνει όλα τα μηνύματα ταξινομημένα με βαση την ημερομηνία καταγραφής σε αύξουσα σειρά (δηλαδή πρώτα οι ημερομηνίες που είναι νωρίτερα). Κάθε γραμμή καταγραφής έχει την μορφή ημερομηνίας με ακρίβεια λεπτού (μορφής \"χρόνος-μήνας-ημέρα Τ ώρες:λεπτά\") ακολουθούμενη από `:` και μετά το μήνυμα της καταγραφής. Παράδειγμα επιτυχούς εκτέλεσης ακολουθεί:\n\n```text\n$ gcc -o sortlog sortlog.c\n$ cat logs.txt\n2024-03-02T13:20: Info: New user 'developer' created successfully.\n2000-07-18T07:00: System startup sequence completed successfully.\n2024-12-12T11:25: 'admin' initiated system reboot after security patch application.\n2024-11-07T08:15: Scheduled backup started for database 'TestDB'.\n2024-12-01T09:00: System startup sequence initiated.\n2024-03-15T05:45: System shutdown sequence initiated.\n2024-03-02T10:30: User 'admin' logged in from IP address 192.168.1.105.\n2024-02-05T16:30: Warning: Disk usage exceeds 85% on drive C:.\n2004-03-09T21:00: Error: Network timeout while connecting to server 'backup.example.com'.\n2025-03-04T14:45: Database connection established successfully.\n$ ./sortlog logs.txt\n2000-07-18T07:00: System startup sequence completed successfully.\n2004-03-09T21:00: Error: Network timeout while connecting to server 'backup.example.com'.\n2024-02-05T16:30: Warning: Disk usage exceeds 85% on drive C:.\n2024-03-02T10:30: User 'admin' logged in from IP address 192.168.1.105.\n2024-03-02T13:20: Info: New user 'developer' created successfully.\n2024-03-15T05:45: System shutdown sequence initiated.\n2024-11-07T08:15: Scheduled backup started for database 'TestDB'.\n2024-12-01T09:00: System startup sequence initiated.\n2024-12-12T11:25: 'admin' initiated system reboot after security patch application.\n2025-03-04T14:45: Database connection established successfully.\n```",
  "hint": "Διαβάστε όλες τις γραμμές σε έναν πίνακα από δείκτες σε δυναμικά δεσμευμένες συμβολοσειρές (δεν ξέρετε ούτε πόσες είναι ούτε πόσο μεγάλες) και ταξινομήστε τον με `qsort`. Παρατηρήστε ότι στη μορφή `ΕΕΕΕ-ΜΜ-ΗΗTΩΩ:ΛΛ` η λεξικογραφική σύγκριση των πρώτων 16 χαρακτήρων συμπίπτει με τη χρονολογική. Ελέγξτε ότι κάθε γραμμή έχει πράγματι αυτή τη μορφή, και σκεφτείτε αν σας ενδιαφέρει η σειρά γραμμών με την ίδια ώρα."
 },
 {
  "id": "exam-2023-fall-ex7-q1",
  "kind": "exam",
  "title": "Ανάβεις Φωτιές",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #7 (Star Wars Themed), Θέμα 1",
   "url": "https://progintro.github.io/exams/2023/fall/ex7/",
   "years": [
    2023
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α9.24",
  "path": "questions/exams/exam-2023-fall-ex7-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex7-q1.html",
  "statement": "Πρόγραμμα: `fire.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα που διαβάζει από την πρότυπη είσοδο (stdin) ένα κείμενο και το τυπώνει στην πρότυπη έξοδο (stdout) αφού πρώτα προσθέσει μια φωτιά 🔥 (χαρακτήρας unicode U+1F525) ακολουθούμενη από κενό στην αρχή κάθε γραμμής. Το υπόλοιπο της πρότασης δεν πρέπει να αλλάζει. Το πρόγραμμά σας πρέπει να χειρίζεται γραμμές οποιουδήποτε μήκους. Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ gcc -o fire fire.c\n$ cat quotes.txt\nMay the force be with you!\nDo... or do not. There is no try.\nIt's a trap�\nI find your lack of faith disturbing.\nI have a very bad feeling about this.\n$ ./fire < quotes.txt\n🔥 May the force be with you!\n🔥 Do... or do not. There is no try.\n🔥 It's a trap�\n🔥 I find your lack of faith disturbing.\n🔥 I have a very bad feeling about this.\n```\n\n> Σημείωση: στο πρωτότυπο το παράδειγμα είναι στιγμιότυπο τερματικού ([εικόνα](https://progintro.github.io/exams/2023/fall/ex7/images/fire.png)).",
  "hint": "Αφού οι γραμμές μπορεί να έχουν οποιοδήποτε μήκος, μην τις αποθηκεύετε: διαβάστε χαρακτήρα προς χαρακτήρα με `getchar` και θυμηθείτε μόνο αν βρίσκεστε στην αρχή γραμμής. Η φωτιά τυπώνεται πριν από τον πρώτο χαρακτήρα κάθε γραμμής, όχι μετά το τελευταίο `'\\n'`. Ο χαρακτήρας U+1F525 σε UTF-8 είναι τέσσερα bytes, που μπορείτε να τα γράψετε μέσα σε ένα string literal."
 },
 {
  "id": "exam-2023-fall-ex7-q2",
  "kind": "exam",
  "title": "Κρυφό Μήνυμα",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #7 (Star Wars Themed), Θέμα 2",
   "url": "https://progintro.github.io/exams/2023/fall/ex7/",
   "years": [
    2023
   ]
  },
  "chapters": [
   18,
   5
  ],
  "topics": [
   "files",
   "bitwise",
   "command-line-args"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α18.12",
  "path": "questions/exams/exam-2023-fall-ex7-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex7-q2.html",
  "statement": "Πρόγραμμα: `r2d2.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα που παίρνει ως ορίσματα δύο ονόματα αρχείων και στην συνέχεια τυπώνει το xor των bytes των δύο αρχείων. Για κάθε byte του πρώτου αρχείου a0, a1, a2 και κάθε byte του δεύτερου αρχείου b0, b1, b2 το πρόγραμμά σας θα πρέπει να τυπώνει τα bytes `a0 xor b0`, `a1 xor b1`, `a2 xor b2`. Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ gcc -o r2d2 r2d2.c\n$ hexdump -C message.txt\n00000000  3b 04 9f da fe db 32 10  28 6a b7 2c c0 a8 bb ee  |;.....2.(j.,....|\n00000010  12 fa 32 1a 3e c7 a8 ec  dd 56 a7 11 c7 e0 07 95  |..2.>....V......|\n...\n00000140  2d cd fe 38 24                                    |-..8$|\n00000145\n$ hexdump -C key.txt\n00000000  68 70 ed b3 95 b2 5c 77  08 0c c5 43 ad 88 da ce  |hp....\\w...C....|\n00000010  74 95 40 6e 4c a2 db 9f  fd 3e ce 75 a3 85 69 b5  |t.@nL....>.u..i.|\n...\n00000140  48 bb 9b 4a 0a                                    |H..J.|\n00000145\n$ ./r2d2 message.txt key.txt\nStriking from a fortress hidden among the billion stars of the galaxy, rebel spaceships have won their first victory in a battle with the powerful Imperial Starfleet. The EMPIRE fears that another defeat could bring a thousand more solar systems into the rebellion, and Imperial control over the galaxy would be lost forever.\n```\n\nΠαρατηρήστε ότι το a0 είναι 0x3b και το b0 είναι 0x68 και το 0x3b xor 0x68 κάνει 0x53 ('S'). Το υπόλοιπο μήνυμα προκύπτει με αντίστοιχο τρόπο.\n\n> Σημείωση: τα δύο hexdump (0x145 = 325 bytes το καθένα) συντομεύτηκαν εδώ· τα αρχεία είναι τα [message.txt](https://progintro.github.io/exams/2023/fall/ex7/message.txt) και [key.txt](https://progintro.github.io/exams/2023/fall/ex7/key.txt).",
  "hint": "Ανοίξτε και τα δύο αρχεία σε δυαδική λειτουργία (`\"rb\"`), διαβάστε ένα byte από το καθένα σε κάθε βήμα με `fgetc` και γράψτε το αποτέλεσμα του τελεστή `^` με `putchar`. Ελέγξτε το `EOF` πριν το χρησιμοποιήσετε ως byte, και αποφασίστε τι σημαίνει το να έχουν τα δύο αρχεία διαφορετικό μήκος."
 },
 {
  "id": "exam-2023-fall-ex7-q3",
  "kind": "exam",
  "title": "Δίδυμοι Πρώτοι",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #7 (Star Wars Themed), Θέμα 3",
   "url": "https://progintro.github.io/exams/2023/fall/ex7/",
   "years": [
    2023
   ]
  },
  "chapters": [
   15,
   13,
   10
  ],
  "topics": [
   "math-algorithms",
   "complexity",
   "dynamic-memory",
   "arrays"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α15.18",
  "path": "questions/exams/exam-2023-fall-ex7-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex7-q3.html",
  "statement": "Πρόγραμμα: `leia.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα που παίρνει ένα εύρος θετικών ακεραίων ως ορίσματα από την κονσόλα (το εύρος είναι κλειστό, δηλαδή περιέχει τα όρια) και τυπώνει πόσα ζεύγη *δίδυμων πρώτων* (twin primes) υπάρχουν σε αυτό το διάστημα. Ένα ζεύγος ακεραίων (n, n+2) είναι δίδυμοι πρώτοι αν και ο n και ο n+2 είναι πρώτοι. Για παράδειγμα, στο διάστημα [1, 10] υπάρχουν μόλις δύο ζεύγη δίδυμων πρώτων (3, 5) και (5, 7). Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ gcc -o leia leia.c\n$ ./leia 1 10\n2\n$ ./leia 10 100\n6\n$ ./leia 1 10000000\n58980\n$ ./leia 100000000000 100000100000\n182\n```",
  "hint": "Ένας έλεγχος πρώτου με δοκιμαστική διαίρεση για κάθε αριθμό του [1, 10^7] είναι αργός· το κόσκινο του Ερατοσθένη σε δυναμικά δεσμευμένο πίνακα είναι η κλασική λύση. Για διαστήματα όπως το [10^11, 10^11 + 10^5] δεν χωράει κόσκινο μέχρι το πάνω όριο: σκεφτείτε ένα «τμηματικό» κόσκινο, που χρησιμοποιεί τους πρώτους μέχρι τη ρίζα του πάνω ορίου για να σημαδέψει μόνο το ζητούμενο διάστημα. Προσέξτε ότι και τα δύο μέλη του ζεύγους πρέπει να είναι μέσα στο διάστημα και ότι οι αριθμοί θέλουν 64 bits."
 },
 {
  "id": "exam-2023-fall-ex7-q4",
  "kind": "exam",
  "title": "Κόψιμο Αρχείων",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #7 (Star Wars Themed), Θέμα 4",
   "url": "https://progintro.github.io/exams/2023/fall/ex7/",
   "years": [
    2023
   ]
  },
  "chapters": [
   18,
   12
  ],
  "topics": [
   "files",
   "command-line-args"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α18.13",
  "path": "questions/exams/exam-2023-fall-ex7-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex7-q4.html",
  "statement": "Πρόγραμμα: `cut.c` (25 μονάδες)\n\nΓράψτε ένα πρόγραμμα το οποίο παίρνει ως όρισμα το όνομα ενός αρχείου που περιέχει δεδομένα και έναν ακέραιο αριθμό από bytes τα οποία θέλουμε να κόψουμε από το τέλος του αρχείου και τυπώνει το νέο αρχείο - έχοντας \"κόψει\" αυτά τα bytes - στην πρότυπη έξοδο. Τα αρχεία θα είναι μέχρι 100MB. Παράδειγμα επιτυχούς εκτέλεσης ακολουθεί:\n\n```text\n$ gcc -o cut cut.c\n$ echo hello world > msg.txt\n$ hexdump -C msg.txt\n00000000  68 65 6c 6c 6f 20 77 6f  72 6c 64 0a              |hello world.|\n0000000c\n$ ./cut msg.txt 6 > msg-cut.txt\n$ hexdump -C msg-cut.txt\n00000000  68 65 6c 6c 6f 20                                 |hello |\n00000006\n$ wc -c imperial.mp3\n2846267 imperial.mp3\n$ ./cut imperial.mp3 2256267 > imperial-cut.mp3\n$ wc -c imperial-cut.mp3\n590000 imperial-cut.mp3\n```",
  "hint": "Βρείτε πρώτα το μέγεθος του αρχείου (π.χ. `fseek` στο τέλος και `ftell`, σε αρχείο ανοιγμένο με `\"rb\"`), υπολογίστε πόσα bytes πρέπει να κρατήσετε και αντιγράψτε ακριβώς τόσα στην έξοδο, κατά προτίμηση σε μπλοκ με `fread`/`fwrite`. Τι κάνετε αν ζητηθεί να κοπούν περισσότερα bytes από όσα έχει το αρχείο, ή αν ο αριθμός είναι αρνητικός ή δεν είναι αριθμός;"
 },
 {
  "id": "exam-2023-fall-ex8-q1",
  "kind": "exam",
  "title": "Άρτια Bits",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #8, Θέμα 1",
   "url": "https://progintro.github.io/exams/2023/fall/ex8/",
   "years": [
    2023
   ]
  },
  "chapters": [
   4,
   12
  ],
  "topics": [
   "bitwise",
   "command-line-args"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α4.13",
  "path": "questions/exams/exam-2023-fall-ex8-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex8-q1.html",
  "statement": "Πρόγραμμα: `parity.c`\n\nΓράψτε ένα πρόγραμμα που παίρνει δεκαδικούς ακεραίους ως ορίσματα από την γραμμή εντολών και τυπώνει για κάθε έναν από αυτούς εάν έχει έναν άρτιο αριθμό από bits που είναι 1 (even parity). Για παράδειγμα ο αριθμός 5 είναι ο 101 στο δυαδικό και επομένως έχει άρτιο αριθμό από bits που είναι 1. Αντίθετα ο αριθμός 7 (111 στο δυαδικό) έχει περιττό αριθμό από bits που έχουν τεθεί στο 1. Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ ./parity 5 7 64 65 987234 97823462\nNumber 5 has even parity\nNumber 7 does not have even parity\nNumber 64 does not have even parity\nNumber 65 has even parity\nNumber 987234 has even parity\nNumber 97823462 does not have even parity\n$ ./parity 92873847981279843\nNumber 92873847981279843 has even parity\n$ ./parity 92873847981279844\nNumber 92873847981279844 does not have even parity\n```",
  "hint": "Μετρήστε τα bits που είναι 1 με μάσκα και ολίσθηση (`&`, `>>`) μέχρι ο αριθμός να γίνει 0. Προσέξτε ότι τα παραδείγματα έχουν αριθμούς πάνω από 2^31, άρα χρειάζεστε 64-bit τύπο (`long long` / `strtoll`) και έλεγχο ότι κάθε όρισμα είναι έγκυρος ακέραιος."
 },
 {
  "id": "exam-2023-fall-ex8-q2",
  "kind": "exam",
  "title": "Αποκωδικοποίηση",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #8, Θέμα 2",
   "url": "https://progintro.github.io/exams/2023/fall/ex8/",
   "years": [
    2023
   ]
  },
  "chapters": [
   9,
   4
  ],
  "topics": [
   "input-output",
   "bitwise",
   "input-validation"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α9.30",
  "path": "questions/exams/exam-2023-fall-ex8-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex8-q2.html",
  "statement": "Πρόγραμμα: `decode.c`\n\nΓράψτε ένα πρόγραμμα που διαβάζει από την πρότυπη είσοδο (stdin) ένα κωδικοποιημένο (ως δεκαεξαδικοί χαρακτήρες) κείμενο και το τυπώνει στην πρότυπη έξοδο (stdout) αποκωδικοποιημένο. Με την δεκαεξαδική κωδικοποίηση κάθε δύο δεκαεξαδικά ψηφία αντιστοιχούν σε έναν χαρακτήρα. Για παράδειγμα τα ψηφία 4b αντιστοιχούν στον δεκαεξαδικό 0x4b που αντιστοιχούν στον χαρακτήρα ascii 'K'. Η αποκωδικοποίηση του υπόλοιπου κειμένου συνεχίζει με τον ίδιο τρόπο. Οποιοσδήποτε χαρακτήρας εισόδου δεν είναι δεκαεξαδικός (a-f, A-F, 0-9) μπορεί να αγνοηθεί. Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ gcc -o decode decode.c\n$ cat encoded_message.txt\n4b65657020796F7572206661636520616C7761797320\n746f77617264207468652073756e7368696e652c2061�\n6e6420736861646f77732077696c6c2066616c6c2062\n6568696e6420796f752e\n$ ./decode < encoded_message.txt\nKeep your face always toward the sunshine, and shadows will fall behind you.\n```",
  "hint": "Διαβάστε την είσοδο χαρακτήρα-χαρακτήρα με `getchar` και αγνοήστε ό,τι δεν είναι δεκαεξαδικό ψηφίο (και τις αλλαγές γραμμής). Μετατρέψτε κάθε ψηφίο στην τιμή του (0–15) και συνδυάστε ανά δύο: το πρώτο είναι τα υψηλά 4 bits. Σκεφτείτε τι κάνετε αν στο τέλος περισσέψει ένα μισό ζεύγος."
 },
 {
  "id": "exam-2023-fall-ex8-q3",
  "kind": "exam",
  "title": "Πολλαπλασιασμός Πινάκων",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #8, Θέμα 3",
   "url": "https://progintro.github.io/exams/2023/fall/ex8/",
   "years": [
    2023
   ]
  },
  "chapters": [
   12,
   18,
   13
  ],
  "topics": [
   "multidim-arrays",
   "dynamic-memory",
   "files",
   "floating-point"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α12.18",
  "path": "questions/exams/exam-2023-fall-ex8-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex8-q3.html",
  "statement": "Πρόγραμμα: `mat_mult.c`\n\nΓράψτε ένα πρόγραμμα που παίρνει ως ορίσματα δύο ονόματα αρχείων που περιέχουν πίνακες αριθμών κινητής υποδιαστολής και στην συνέχεια τυπώνει το γινόμενο των δύο πινάκων με ακρίβεια δύο δεκαδικών ψηφίων. Στην πρώτη γραμμή κάθε αρχείου περιέχονται οι διαστάσεις του πίνακα (γραμμές και στήλες). Σύμφωνα με τον ορισμό, το γινόμενο δύο πινάκων A ($a_{ij}$) και B ($b_{jk}$) είναι ένας πίνακας C όπου $$c_{ij} = \\sum_{k=1}^n a_{ik}b_{kj}$$\n\nΠαράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ gcc -o mat_mult mat_mult.c\n$ cat mat1.txt\n2 3\n1.12 2.01 3.22\n4.08 5.02 6.05\n$ cat mat2.txt\n3 2\n7      7.99\n 9.09 10.0\n11.11 12.21\n$ ./mat_mult mat1.txt mat2.txt\n61.89 68.37\n141.41 156.67\n```",
  "hint": "Διαβάστε πρώτα τις διαστάσεις και δεσμεύστε δυναμικά τον πίνακα με το σωστό μέγεθος· ελέγξτε ότι το αρχείο ανοίγει και ότι περιέχει όσα στοιχεία δηλώνουν οι διαστάσεις. Το γινόμενο ορίζεται μόνο όταν οι στήλες του πρώτου ισούνται με τις γραμμές του δεύτερου· αλλιώς είναι είσοδος εκτός προδιαγραφών."
 },
 {
  "id": "exam-2023-fall-ex8-q4",
  "kind": "exam",
  "title": "Ταξινόμηση Πακέτων",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #8, Θέμα 4",
   "url": "https://progintro.github.io/exams/2023/fall/ex8/",
   "years": [
    2023
   ]
  },
  "chapters": [
   18,
   13,
   14
  ],
  "topics": [
   "sorting",
   "files",
   "strings",
   "dynamic-memory"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α18.23",
  "path": "questions/exams/exam-2023-fall-ex8-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex8-q4.html",
  "statement": "Πρόγραμμα: `packet.c`\n\nΓράψτε ένα πρόγραμμα το οποίο παίρνει ως όρισμα το όνομα ενός αρχείου που περιέχει πακέτα ακολουθούμενα από κόμμα `,` και στην συνέχεια έναν αύξοντα αριθμό (packet id) που δείχνει που έπρεπε να βρίσκονται κανονικά στην σειρά των πακέτων και τυπώνει τα πακέτα ταξινομημένα σε αύξουσα σειρά με βάση τους αύξοντες αριθμούς. Παράδειγμα επιτυχούς εκτέλεσης ακολουθεί:\n\n```text\n$ gcc -o packet packet.c\n$ cat unordered.txt\nHello from five,5\nThis is the first packet,1\nContinuing with seven,7\nAlmost there,9\nMiddle of the sequence,6\nStarting to make sense,8\nThe very last packet,10\nSecond in line,2\nGetting closer,4\nThird packet coming through,3\n$ ./packet unordered.txt\nThis is the first packet,1\nSecond in line,2\nThird packet coming through,3\nGetting closer,4\nHello from five,5\nMiddle of the sequence,6\nContinuing with seven,7\nStarting to make sense,8\nAlmost there,9\nThe very last packet,10\n```",
  "hint": "Αποθηκεύστε κάθε γραμμή μαζί με το packet id της (το κείμενο μετά το τελευταίο κόμμα) και ταξινομήστε με `qsort` και κατάλληλη συνάρτηση σύγκρισης. Δεν ξέρετε εκ των προτέρων πόσες γραμμές ή πόσο μεγάλη θα είναι η καθεμία, οπότε χρειάζεστε δυναμικούς πίνακες που μεγαλώνουν με `realloc`."
 },
 {
  "id": "exam-2023-fall-ex9-q1",
  "kind": "exam",
  "title": "Έλεγχος Εκτελέσιμου",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #9, Θέμα 1",
   "url": "https://progintro.github.io/exams/2023/fall/ex9/",
   "years": [
    2023
   ]
  },
  "chapters": [
   18
  ],
  "topics": [
   "files"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α18.14",
  "path": "questions/exams/exam-2023-fall-ex9-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex9-q1.html",
  "statement": "Πρόγραμμα: `elf.c`\n\nΓράψτε ένα πρόγραμμα που παίρνει ως όρισμα το όνομα ενός αρχείου και αποφαίνεται για το αν το αρχείο είναι ένα Linux εκτελέσιμο ELF (Executable and Linking Format) ή όχι. Ένα αρχείο θεωρείται ELF όταν ξεκινάει με τους χαρακτήρες 0x7f, E, L, F. Οποιοδήποτε άλλο αρχείο δεν θεωρείται ELF. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ gcc -o elf elf.c\n$ ./elf foo\nError: Unable to read file\n$ ./elf message.txt\nmessage.txt is NOT an ELF file.\n$ ./elf ./elf.c\n./elf.c is NOT an ELF file.\n$ ./elf ./elf\n./elf is an ELF file.\n$ ./elf /bin/ls\n/bin/ls is an ELF file.\n$ ./elf /lib/x86_64-linux-gnu/libc.so.6\n/lib/x86_64-linux-gnu/libc.so.6 is an ELF file.\n```",
  "hint": "Ανοίξτε το αρχείο σε δυαδική μορφή (`\"rb\"`) και διαβάστε μόνο τα πρώτα 4 bytes. Σκεφτείτε τις ακραίες περιπτώσεις: αρχείο που δεν ανοίγει, αρχείο με λιγότερα από 4 bytes, λάθος πλήθος ορισμάτων."
 },
 {
  "id": "exam-2023-fall-ex9-q2",
  "kind": "exam",
  "title": "Πετυχαίνοντας τον Στόχο",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #9, Θέμα 2",
   "url": "https://progintro.github.io/exams/2023/fall/ex9/",
   "years": [
    2023
   ]
  },
  "chapters": [
   6,
   12
  ],
  "topics": [
   "loops",
   "command-line-args",
   "integer-representation"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α6.24",
  "path": "questions/exams/exam-2023-fall-ex9-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex9-q2.html",
  "statement": "Πρόγραμμα: `legolas.c`\n\nΓράψτε ένα πρόγραμμα το οποίο παίρνει ως ορίσματα από την γραμμή εντολών έναν ακέραιο-στόχο (goal) και στην συνέχεια ένα σύνολο υποψηφίων ακεραίων (candidates) και τυπώνει όλους τους συνδυασμούς 3 υποψηφίων των οποίων το άθροισμα ισούται με τον στόχο. Η σειρά με την οποία εκτυπώνονται τα αποτελέσματα δεν έχει σημασία για την ορθότητα του προγράμματος. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ gcc -o legolas legolas.c\n$ ./legolas 42 19 21 3 5 12\nNo combination of candidates leads to 42\n$ ./legolas 42 19 21 3 5 12 11\nCandidates combination found: 19 + 12 + 11 = 42\n$ ./legolas 42 27 25 12 31 5 26 40 34 3 18\nCandidates combination found: 27 + 12 + 3 = 42\nCandidates combination found: 25 + 12 + 5 = 42\nCandidates combination found: 5 + 34 + 3 = 42\n$ ./legolas 37372082074 9238742398 82934723 27893492387 127863435 239847289\nCandidates combination found: 9238742398 + 27893492387 + 239847289 = 37372082074\n```",
  "hint": "Τρεις φωλιασμένοι βρόχοι με δείκτες i < j < k δίνουν κάθε τριάδα υποψηφίων ακριβώς μία φορά. Το τελευταίο παράδειγμα έχει αριθμούς που δεν χωρούν σε `int`: χρησιμοποιήστε `long long` και κρατήστε αν βρέθηκε έστω ένας συνδυασμός για το τελικό μήνυμα."
 },
 {
  "id": "exam-2023-fall-ex9-q3",
  "kind": "exam",
  "title": "Πολύτιμοι Πίνακες",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #9, Θέμα 3",
   "url": "https://progintro.github.io/exams/2023/fall/ex9/",
   "years": [
    2023
   ]
  },
  "chapters": [
   12,
   18,
   13
  ],
  "topics": [
   "multidim-arrays",
   "files",
   "dynamic-memory"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α12.19",
  "path": "questions/exams/exam-2023-fall-ex9-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex9-q3.html",
  "statement": "Πρόγραμμα: `precious.c`\n\nΈνας πίνακας ακεραίων λέγεται πολύτιμος όταν το άθροισμα των στοιχείων της κάθε γραμμής ισούται με το άθροισμα των στοιχείων της κάθε στήλης. Γράψτε ένα πρόγραμμα που δέχεται το όνομα ενός αρχείου που περιέχει έναν πίκανα ως πρώτο όρισμα και τυπώνει εάν ο πίνακας είναι πολύτιμος. Το αρχείο που περιέχει τον πίνακα ξεκινά με τις διαστάσεις του πίνακα και συνεχίζει με τους ακεραίους που αποτελούν τα στοιχεία του. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ gcc -o precious precious.c\n$ cat ring.txt\n3 3\n8 1 6\n3 5 7\n4 9 2\n$ ./precious ring.txt\nMy precious!\n$ cat not-ring.txt\n3 4\n6 1 6 2\n7 5 1 2\n4 9 8 9\n$ ./precious not-ring.txt\nThis matrix is NOT precious.\n```\n\nΓια παράδειγμα ο πρώτος πίνακας είναι πολύτιμος καθώς κάθε γραμμή και κάθε στήλη αθροίζει στον ίδιο ακέραιο (το 15).",
  "hint": "Διαβάστε πρώτα τις διαστάσεις και δεσμεύστε δυναμικά τον πίνακα με το σωστό μέγεθος· ελέγξτε ότι το αρχείο ανοίγει και ότι περιέχει όσα στοιχεία δηλώνουν οι διαστάσεις. Υπολογίστε το άθροισμα μιας γραμμής ως αναφορά και συγκρίνετε με αυτό όλα τα αθροίσματα γραμμών και στηλών (ο πίνακας δεν χρειάζεται να είναι τετράγωνος)."
 },
 {
  "id": "exam-2023-fall-ex9-q4",
  "kind": "exam",
  "title": "Κάδρο",
  "source": {
   "title": "Online τελική εξέταση Δεκεμβρίου 2023, Εξέταση #9, Θέμα 4",
   "url": "https://progintro.github.io/exams/2023/fall/ex9/",
   "years": [
    2023
   ]
  },
  "chapters": [
   13,
   9,
   14
  ],
  "topics": [
   "dynamic-memory",
   "input-output",
   "strings"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α13.11",
  "path": "questions/exams/exam-2023-fall-ex9-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2023-fall-ex9-q4.html",
  "statement": "Πρόγραμμα: `frame.c`\n\nΓράψτε ένα πρόγραμμα που διαβάζει από την πρότυπη είσοδο (stdin) ένα κείμενο λατινικών χαρακτήρων και το τυπώνει στην πρότυπη έξοδο (stdout) εντός ενός τετράγωνου κάδρου. Το κάδρο αποτελείται από τον χαρακτήρα '*' (42 στο δεκαδικό). Το πρόγραμμά σας πρέπει να μπορεί να χειριστεί οποιονδήποτε αριθμό γραμμών κάθε μία από τις οποίες μπορεί να είναι οποιουδήποτε μεγέθους. Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ cat message.txt\n    One Ring to\n   Rule them all\n    One Ring to\n     find them\n    One Ring to\n   Bring them all\nand in the darkness\n    Bind them\n$ gcc -o frame frame.c\n$ ./frame < message.txt\n*********************\n*    One Ring to    *\n*   Rule them all   *\n*    One Ring to    *\n*     find them     *\n*    One Ring to    *\n*   Bring them all  *\n*and in the darkness*\n*    Bind them      *\n*********************\n```",
  "hint": "Το πλάτος του κάδρου εξαρτάται από τη μεγαλύτερη γραμμή, άρα πρέπει να διαβάσετε όλη την είσοδο πριν τυπώσετε οτιδήποτε. Δεν ξέρετε εκ των προτέρων πόσες γραμμές ή πόσο μεγάλη θα είναι η καθεμία, οπότε χρειάζεστε δυναμικούς πίνακες που μεγαλώνουν με `realloc`. Κάθε γραμμή συμπληρώνεται με κενά ως το μέγιστο μήκος."
 },
 {
  "id": "exam-2024-dec-q1",
  "kind": "exam",
  "title": "Προσεγγίζοντας το π",
  "source": {
   "title": "Κατατακτήριες Δεκεμβρίου 2024, Θέμα 1",
   "url": "https://progintro.github.io/exams/2024/progintro-exam-dec-24.pdf",
   "years": [
    2024
   ]
  },
  "chapters": [
   6,
   3,
   4
  ],
  "topics": [
   "loops",
   "floating-point",
   "command-line-args"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α6.17",
  "path": "questions/exams/exam-2024-dec-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2024-dec-q1.html",
  "statement": "Ο Άγγλος μαθηματικός John Wallis θεωρείται πως είναι ένας από τους πρώτους που\nεισήγαγε την έννοια του απείρου ($\\infty$) στα μαθηματικά. Το 1656 δημοσίευσε ένα\nαποτέλεσμα σύμφωνα με το οποίο μπορούμε να προσεγγίσουμε το $\\pi$ χρησιμοποιώντας το\nακόλουθο απειρογινόμενο όρων $t_i$, γνωστό και ως γινόμενο Wallis προς τιμήν του:\n\n$$\\frac{\\pi}{2} = \\underbrace{\\frac{2}{1} \\cdot \\frac{2}{3}}_{t_1} \\cdot \\underbrace{\\frac{4}{3} \\cdot \\frac{4}{5}}_{t_2} \\cdot \\underbrace{\\frac{6}{5} \\cdot \\frac{6}{7}}_{t_3} \\cdot \\underbrace{\\frac{8}{7} \\cdot \\frac{8}{9}}_{t_4} \\cdots$$\n\nΧρησιμοποιώντας την παραπάνω σχέση μπορούμε να προσεγγίσουμε και εμείς το $\\pi$ όπως ο\nWallis. Μάλιστα, όσους περισσότερους όρους $t_i$ χρησιμοποιούμε, τόσο καλύτερη η\nπροσέγγισή μας. Γράψτε ένα πρόγραμμα C το οποίο παίρνει έναν θετικό ακέραιο ως όρισμα\nαπό την γραμμή εντολών που αντιπροσωπεύει πόσους πρώτους όρους $t_i$ να χρησιμοποιήσει\nστον υπολογισμό του $\\pi$ και στην συνέχεια εκτυπώνει την προσέγγιση του $\\pi$ με 8\nδεκαδικά ψηφία. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ ./wallis\nUsage: ./wallis <number of terms to use>\n$ echo $?\n1\n$ ./wallis 1\nUsing the first 1 terms, pi = 2.66666667\n$ ./wallis 2\nUsing the first 2 terms, pi = 2.84444444\n$ ./wallis 4\nUsing the first 4 terms, pi = 2.97215420\n$ ./wallis 100\nUsing the first 100 terms, pi = 3.13378749\n$ ./wallis 100000000\nUsing the first 100000000 terms, pi = 3.14159264\n```",
  "hint": "Γράψτε τον γενικό όρο $t_i$ ως συνάρτηση του $i$ και πολλαπλασιάστε τους σε έναν βρόχο,\nμε μεταβλητή `double`: προσέξτε ότι οι διαιρέσεις πρέπει να γίνονται σε κινητή\nυποδιαστολή και ότι για $i$ ως $10^8$ το γινόμενο $2i \\cdot 2i$ χρειάζεται τύπο αρκετά\nμεγάλο. Μην ξεχάσετε ότι το γινόμενο δίνει $\\pi/2$, και ελέγξτε το `argc` ώστε να\nτυπώνετε το μήνυμα χρήσης και να επιστρέφετε κωδικό εξόδου 1."
 },
 {
  "id": "exam-2024-dec-q2",
  "kind": "exam",
  "title": "Οι Καλύτεροι Αριθμοί, Παμψηφεί",
  "source": {
   "title": "Κατατακτήριες Δεκεμβρίου 2024, Θέμα 2",
   "url": "https://progintro.github.io/exams/2024/progintro-exam-dec-24.pdf",
   "years": [
    2024
   ]
  },
  "chapters": [
   16,
   2
  ],
  "topics": [
   "math-algorithms",
   "loops",
   "command-line-args",
   "integer-representation"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α16.24",
  "path": "questions/exams/exam-2024-dec-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2024-dec-q2.html",
  "statement": "Στα μαθηματικά, ένας φυσικός αριθμός $n$ λέγεται *πανψηφιακός* (pandigital) ως προς μια\nβάση $b$ όταν περιέχει *τουλάχιστον* μία φορά όλα τα ψηφία από το 0 μέχρι το $b - 1$.\nΓια παράδειγμα, ο αριθμός 1234567890 είναι πανψηφιακός με βάση το 10 όπως και ο αριθμός\n90123456789 (τα ψηφία μπορούν να επαναλαμβάνονται και η σειρά τους δεν έχει σημασία).\n\nΓράψτε ένα πρόγραμμα C το οποίο βρίσκει και τυπώνει όλους τους πανψηφιακούς αριθμούς\nμε βάση το 10 σε ένα εύρος φυσικών αριθμών $[low, high]$ (το εύρος είναι κλειστό, δηλαδή\nτα άκρα συμπεριλαμβάνονται), όπου οι αριθμοί δίνονται από την γραμμή εντολών. Οι\nαριθμοί του εύρους δεν θα υπερβούν το $2^{64} - 1$. Ακολουθεί παράδειγμα εκτέλεσης για\nνα βρούμε όλους τους πανψηφιακούς αριθμούς στο διάστημα $[1000000000, 1300000000]$:\n\n```text\n$ ./pandigital 1000000000 1300000000\nAll pandigital numbers in the range 1000000000 to 1300000000 follow:\n1023456789\n1023456798\n1023456879\n1023456897\n...\n1298765304\n1298765340\n1298765403\n1298765430\n```",
  "hint": "Τα όρια χωράνε μόνο σε `unsigned long long`, οπότε διαβάστε τα με `strtoull` και\nπροσέξτε τον βρόχο όταν `high` είναι η μέγιστη τιμή του τύπου (ο μετρητής δεν πρέπει να\nυπερχειλίσει). Για κάθε αριθμό βγάλτε τα ψηφία του με `% 10` και `/ 10` και σημειώστε\nποια εμφανίστηκαν, π.χ. σε μια μάσκα 10 bit. Αριθμοί με λιγότερα από 10 ψηφία δεν\nμπορούν να είναι πανψηφιακοί."
 },
 {
  "id": "exam-2024-dec-q3",
  "kind": "exam",
  "title": "Η Τριπλέτα Στόχος",
  "source": {
   "title": "Κατατακτήριες Δεκεμβρίου 2024, Θέμα 3",
   "url": "https://progintro.github.io/exams/2024/progintro-exam-dec-24.pdf",
   "years": [
    2024
   ]
  },
  "chapters": [
   25,
   17,
   13
  ],
  "topics": [
   "sorting",
   "complexity",
   "dynamic-memory",
   "problem-solving"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α25.11",
  "path": "questions/exams/exam-2024-dec-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2024-dec-q3.html",
  "statement": "Γράψτε ένα πρόγραμμα το οποίο παίρνει ως όρισμα από την γραμμή εντολών έναν\nακέραιο-στόχο (goal) και από την πρότυπη είσοδο (stdin) ένα σύνολο διαφορετικών\nυποψηφίων ακεραίων (candidates) και τυπώνει όλες τις πιθανές τριπλέτες υποψηφίων\nακεραίων των οποίων το άθροισμα ισούται με τον στόχο. Ο κάθε υποψήφιος ακέραιος μπορεί\nνα χρησιμοποιηθεί μέχρι μία φορά σε κάθε τριπλέτα. Για παράδειγμα αν δοθεί ο στόχος 10\nκαι οι ακέραιοι 6, 1, 7, 2, 3 ως υποψήφιοι για τις τριπλέτες υπάρχουν ακριβώς δύο\nσυνδυασμοί που οδηγούν στον στόχο: $1 + 3 + 6 = 10$ και $1 + 2 + 7 = 10$ (ο συνδυασμός\n$6 + 2 + 2 = 10$ *δεν* είναι δεκτός καθώς ο ακέραιος 2 επαναλαμβάνεται).\n\nΟ αλγόριθμός σας πρέπει να έχει χρονική πολυπλοκότητα γρηγορότερη από $O(n^3)$, όπου\n$n$ είναι ο αριθμός των ακεραίων που σας δίνονται. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ ./triplet 10\nProvide the numbers: 6 1 7 2 3\nTriplet found: 1 + 2 + 7 = 10\nTriplet found: 1 + 3 + 6 = 10\n$ ./triplet 42\nProvide the numbers: 1 2 3\nNo triplet leads to 42\n$ ./triplet 42\nProvide the numbers: 19 21 3 5 12 11\nTriplet found: 11 + 12 + 19 = 42\n$ ./triplet 42\nProvide the numbers: 42 27 25 12 31 5 26 40 34 3 18\nTriplet found: 3 + 5 + 34 = 42\nTriplet found: 3 + 12 + 27 = 42\nTriplet found: 5 + 12 + 25 = 42\n```",
  "hint": "Το πλήθος των αριθμών δεν είναι γνωστό από πριν, οπότε διαβάστε τους μέχρι το EOF σε\nπίνακα που μεγαλώνει με `realloc`. Ταξινομήστε τον πρώτα: αυτό κάνει τις τριπλέτες να\nβγαίνουν σε αύξουσα σειρά, όπως στα παραδείγματα, και σας επιτρέπει, για σταθερό\nμικρότερο στοιχείο, να ψάξετε τα άλλα δύο με δύο δείκτες που κινούνται ο ένας προς τον\nάλλον, αντί για τρίτο εμφωλευμένο βρόχο."
 },
 {
  "id": "exam-2024-dec-q4",
  "kind": "exam",
  "title": "Λύσε τον Λαβύρινθο",
  "source": {
   "title": "Κατατακτήριες Δεκεμβρίου 2024, Θέμα 4",
   "url": "https://progintro.github.io/exams/2024/progintro-exam-dec-24.pdf",
   "years": [
    2024
   ]
  },
  "chapters": [
   25,
   12,
   11
  ],
  "topics": [
   "dynamic-programming",
   "multidim-arrays",
   "recursion",
   "complexity"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α25.12",
  "path": "questions/exams/exam-2024-dec-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2024-dec-q4.html",
  "statement": "> Σημείωση: το πρωτότυπο ξεκινά με το Σχήμα 1, δύο εικόνες του λαβυρίνθου 7x7 του\n> αρχείου `maze.txt` παρακάτω: (i) ο αρχικός λαβύρινθος, όπου ξεκινάμε στο (0, 0) και\n> θέλουμε να φτάσουμε στο (6, 6), και (ii) μια ενδεικτική λύση, όπου επιτρέπονται\n> κινήσεις μόνο προς τα κάτω (D) και δεξιά (R). Οι εικόνες υπάρχουν στο PDF της εξέτασης.\n\n*Σχήμα 1: Οπτικοποίηση ενός λαβυρίνθου και της λύσης του. Παρατηρήστε ότι το ρομπότ μας\nξεκινάει πάντα την διαδρομή του στο (0,0) και ολοκληρώνει την διαδρομή του στο (Ν-1, Ν-1)\nόπου Ν η διάσταση του λαβυρίνθου.*\n\nΣε αυτό το πρόβλημα θα προγραμματίσουμε ένα ρομπότ το οποίο μπορεί να βρίσκει την έξοδο\nσε μια κατηγορία τετραγωνικών λαβυρίνθων, όπου η είσοδος είναι πάνω αριστερά και η έξοδος\nκάτω δεξιά. Για λόγους οικονομίας, το ρομπότ μας μπορεί να κινηθεί μόνο προς τα κάτω\n(D - Down) ή προς τα δεξιά (R - Right) σε κάθε βήμα. Το Σχήμα 1 δείχνει ένα παράδειγμα με\nτο ρομπότ μας να βρίσκει το μονοπάτι DDDDRRRRDDRR και να φτάνει στην έξοδο.\n\nΓράψτε ένα πρόγραμμα C που διαβάζει τον πίνακα με τα περιεχόμενα του λαβυρίνθου και\nτυπώνει (εφόσον υπάρχει) ένα βέλτιστο μονοπάτι για να φτάσει το ρομπότ μας στην έξοδο.\nΤο πρόγραμμά σας πρέπει να διαβάζει τον λαβύρινθο από την πρότυπη είσοδο όπου θα\nδίνονται: (1) στην πρώτη γραμμή η διάσταση του τετραγωνικού πλέγματος, και (2) στην\nσυνέχεια τα περιεχόμενα του λαβυρίνθου όπου \"1\" θα συμβολίζει ένα κελί με τοίχο και \"0\"\nθα συμβολίζει το κενό. Το πρόγραμμά σας πρέπει να είναι αποδοτικό σε χρονική και χωρική\nπολυπλοκότητα. Αφού ολοκληρώσετε το πρόγραμμά σας, καταγράψτε και εξηγήστε την\nπολυπλοκότητά του ως προς τον χρόνο και τον χώρο μνήμης που απαιτεί. Ακολουθούν\nενδεικτικές εκτελέσεις:\n\n```text\n$ cat maze.txt\n7\n0001000\n0111010\n0100010\n0101110\n0000010\n0111010\n0100000\n$ ./robot < maze.txt\nPath: DDDDRRRRDDRR\n$ cat nopath.txt\n7\n0001000\n0111010\n0100010\n0101110\n0000010\n0111110\n0100000\n$ ./robot < nopath.txt\nNo path found\n```",
  "hint": "Αφού κινούμαστε μόνο κάτω και δεξιά, κάθε μονοπάτι έχει ακριβώς $2N-2$ βήματα, άρα το\nερώτημα είναι μόνο αν υπάρχει. Μια αναδρομική δοκιμή όλων των διαδρομών είναι εκθετική·\nαντί γι' αυτό, συμπληρώστε έναν δισδιάστατο πίνακα που λέει για κάθε κελί αν από εκεί\nφτάνουμε στην έξοδο (ή αποθηκεύστε τα αποτελέσματα της αναδρομής), ώστε κάθε κελί να\nεξετάζεται μία φορά. Προσέξτε τις περιπτώσεις όπου η αρχή ή η έξοδος είναι τοίχος και\nτον τρόπο που διαβάζετε γραμμές ψηφίων χωρίς κενά."
 },
 {
  "id": "exam-2024-jul-q1",
  "kind": "exam",
  "title": "ASCII Encoding",
  "source": {
   "title": "Εξέταση Ιουλίου 2024, Θέμα 1",
   "url": "https://progintro.github.io/exams/2024/progintro-exam-jul-24.pdf",
   "years": [
    2024
   ]
  },
  "chapters": [
   9,
   2
  ],
  "topics": [
   "input-output",
   "loops",
   "integer-representation"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α9.25",
  "path": "questions/exams/exam-2024-jul-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2024-jul-q1.html",
  "statement": "Γράψτε ένα πρόγραμμα το οποίο διαβάζει όλους τους χαρακτήρες που δίνονται από την\nπρότυπη είσοδο (stdin) και τυπώνει στην πρότυπη έξοδο (stdout) την δεκαεξαδική\nαναπαράστασή τους με μία εξαίρεση: οι χαρακτήρες νέας γραμμής (newline) πρέπει να\nτυπώνονται ως έχουν - χωρίς μετατροπή σε δεκαεξαδική μορφή. Παράδειγμα εκτέλεσης\nακολουθεί:\n\n```text\n$ cat ithaka.txt\nAs you set out for Ithaka\nhope your road is a long one,\nfull of adventure, full of discovery.\n$ ./ascii < ithaka.txt\n417320796f7520736574206f757420666f7220497468616b61\n686f706520796f757220726f61642069732061206c6f6e67206f6e652c\n66756c6c206f6620616476656e747572652c2066756c6c206f6620646973636f766572792e\n```",
  "hint": "Διαβάστε την είσοδο χαρακτήρα προς χαρακτήρα μέχρι το `EOF`, προσέχοντας τον τύπο της\nμεταβλητής που κρατά το αποτέλεσμα της `getchar`. Η `printf` έχει έτοιμο προσδιοριστή\nγια δεκαεξαδική μορφή· σκεφτείτε πώς εξασφαλίζετε ότι κάθε χαρακτήρας βγαίνει πάντα με\nδύο ψηφία (π.χ. για χαρακτήρες με κωδικό μικρότερο του 16)."
 },
 {
  "id": "exam-2024-jul-q2",
  "kind": "exam",
  "title": "Στατιστικές",
  "source": {
   "title": "Εξέταση Ιουλίου 2024, Θέμα 2",
   "url": "https://progintro.github.io/exams/2024/progintro-exam-jul-24.pdf",
   "years": [
    2024
   ]
  },
  "chapters": [
   12,
   10
  ],
  "topics": [
   "command-line-args",
   "floating-point",
   "arrays"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α12.20",
  "path": "questions/exams/exam-2024-jul-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2024-jul-q2.html",
  "statement": "Γράψτε ένα πρόγραμμα το οποίο δέχεται ακεραίους ως ορίσματα από την γραμμή εντολών και\nτυπώνει στην πρότυπη έξοδο (stdout) τον μέσο όρο τους και την τυπική απόκλιση με 3\nδεκαδικά ψηφία ακρίβεια. Υπενθυμίζεται ότι ο μέσος όρος μ για Ν όρους δίνεται από τον\nτύπο: $\\mu = \\frac{\\sum x_i}{N}$ και η τυπική απόκλιση δίνεται από τον τύπο:\n$\\sigma = \\sqrt{\\frac{\\sum (x_i - \\mu)^2}{N}}$. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ ./stats 8 4 12\nMean: 8.000, Standard deviation: 3.266\n$ ./stats 8 4 12 23 2 3 42 432 2 22 3 4 2 3 2 32 3 23\nMean: 34.556, Standard deviation: 97.112\n```",
  "hint": "Τα ορίσματα βρίσκονται στο `argv` ως συμβολοσειρές, οπότε χρειάζεστε μετατροπή σε\nακέραιο, και το πλήθος τους είναι `argc - 1`. Η τυπική απόκλιση θέλει τον μέσο όρο ήδη\nυπολογισμένο, άρα κάντε δύο περάσματα πάνω στα ορίσματα. Κάντε τις πράξεις σε `double`\n(όχι ακέραια διαίρεση), θυμηθείτε το `-lm` για την `sqrt` και σκεφτείτε τι γίνεται\nόταν δεν δοθεί κανένα όρισμα."
 },
 {
  "id": "exam-2024-jul-q3",
  "kind": "exam",
  "title": "Βέλτιστη Μοιρασιά Πίτσας",
  "source": {
   "title": "Εξέταση Ιουλίου 2024, Θέμα 3",
   "url": "https://progintro.github.io/exams/2024/progintro-exam-jul-24.pdf",
   "years": [
    2024
   ]
  },
  "chapters": [
   25,
   17,
   15
  ],
  "topics": [
   "sorting",
   "complexity",
   "problem-solving",
   "arrays"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α25.13",
  "path": "questions/exams/exam-2024-jul-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2024-jul-q3.html",
  "statement": "Παραγγείλατε πίτσες για να δείτε τον τελικό του Euro και διαπιστώσατε τελευταία στιγμή\nπως ήρθαν υπερβολικά πολλοί καλεσμένοι (ως συνήθως κάποιοι αυτοπροσκλήθηκαν). Παρόλα\nαυτά κάνατε την καρδιά σας πέτρα και αποφασίσατε να ταΐσετε όσους περισσότερους γίνεται.\nΚαι τι καλύτερος τρόπος για να γίνει αυτό παρά μέσα από ένα πρόγραμμα - περνάς ευχάριστα\nτον χρόνο σου όσο παίζουν οι διαφημίσεις.\n\nΓράψτε ένα πρόγραμμα το οποίο διαβάζει από την πρότυπη είσοδο: (1) τον αριθμό από\nπίτσες που έχουμε, (2) τον αριθμό κομματιών κάθε πίτσας, (3) τον αριθμό των ατόμων που\nέχουμε, (4) τον αριθμό των κομματιών που επιθυμεί το κάθε άτομο και τυπώνει στην\nπρότυπη έξοδο τον μέγιστο αριθμό ατόμων που μπορούμε να ικανοποιήσουμε **πλήρως** (αν\nκάποιο άτομο επιθυμεί 5 κομμάτια, πρέπει να φάει 5, αν απλά φάει 1 δεν αρκεί).\nΠεριγράψτε την χρονική και χωρική πολυπλοκότητα του αλγορίθμου σας και εξηγήστε αν\nείναι η βέλτιστη (8/25 της βαθμολογίας). Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ ./pizza\nNumber of pizzas available: 3\nEnter the number of slices for each pizza: 8 10 5\nNumber of people: 4\nNumber of slices desired by each person: 6 9 7 5\nMax number of people that can be satisfied: 3\n```",
  "hint": "Για να ικανοποιήσετε όσο το δυνατόν περισσότερα άτομα, ποιους συμφέρει να\nεξυπηρετήσετε πρώτους; Σκεφτείτε μια άπληστη (greedy) στρατηγική που βασίζεται σε\nταξινόμηση των επιθυμιών, και αιτιολογήστε γιατί καμία άλλη επιλογή δεν δίνει\nπερισσότερα άτομα. Οι πίνακες έχουν μέγεθος που δίνεται στην είσοδο, και η\nπολυπλοκότητα καθορίζεται κυρίως από τον αλγόριθμο ταξινόμησης που θα διαλέξετε."
 },
 {
  "id": "exam-2024-jul-q4",
  "kind": "exam",
  "title": "Reverse Inorder Traversal",
  "source": {
   "title": "Εξέταση Ιουλίου 2024, Θέμα 4",
   "url": "https://progintro.github.io/exams/2024/progintro-exam-jul-24.pdf",
   "years": [
    2024
   ]
  },
  "chapters": [
   22,
   11,
   15
  ],
  "topics": [
   "trees",
   "recursion",
   "complexity"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α22.19",
  "path": "questions/exams/exam-2024-jul-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2024-jul-q4.html",
  "statement": "Γράψτε μια συνάρτηση `reverse_inorder` η οποία παίρνει ως όρισμα ένα δέντρο ακεραίων\nτύπου `Tree` και τυπώνει τους αριθμούς των κόμβων σε σειρά reverse inorder traversal,\nδηλαδή όπως βλέπουμε τους αριθμούς από δεξιά προς τα αριστερά (πρώτο το δεξί παιδί, μετά\nο γονιός και στην συνέχεια το αριστερό). Για παράδειγμα, για το ακόλουθο δέντρο:\n\n```mermaid\nflowchart TD\n  N1((\"1\")) --> N2((\"2\"))\n  N1 --> N3((\"3\"))\n  N2 --> N4((\"4\"))\n  N2 --> N5((\"5\"))\n  N3 --> N6((\"6\"))\n  N3 --> N7((\"7\"))\n```\n\n*Σχήμα: το δέντρο του παραδείγματος.*\n\nπεριμένουμε να εκτυπωθεί η ακολουθία: 7 3 6 1 5 2 4. Ποια είναι η χρονική και η χωρική\nπολυπλοκότητα του αλγορίθμου σας (8/25 της βαθμολογίας); Ο τύπος `Tree` δίνεται\nπαρακάτω:\n\n```c\ntypedef struct node {\n  int value;\n  struct node * left;\n  struct node * right;\n} * Tree;\n```",
  "hint": "Ξεκινήστε από την αναδρομική inorder διάσχιση και αλλάξτε τη σειρά με την οποία\nεπισκέπτεστε τα δύο υποδέντρα. Μην ξεχάσετε τη βασική περίπτωση του κενού δέντρου\n(`NULL`). Για τη χωρική πολυπλοκότητα, σκεφτείτε πόσο βαθιά μπορεί να φτάσει η στοίβα\nτων αναδρομικών κλήσεων στη χειρότερη περίπτωση."
 },
 {
  "id": "exam-2024-sep-q1",
  "kind": "exam",
  "title": "Η συνάρτηση about",
  "source": {
   "title": "Εξέταση Σεπτεμβρίου 2024, Θέμα 1",
   "url": "https://progintro.github.io/exams/2024/progintro-exam-sep-24.pdf",
   "years": [
    2024
   ]
  },
  "chapters": [
   3,
   2
  ],
  "topics": [
   "input-output",
   "functions",
   "strings"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α3.8",
  "path": "questions/exams/exam-2024-sep-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2024-sep-q1.html",
  "statement": "**About [5 Μονάδες]**\n\nΓράψτε μια συνάρτηση `about` η οποία τυπώνει 3 γραμμές στην πρότυπη έξοδο (stdout):\n1) το όνομά σας με λατινικούς χαρακτήρες στην 1η, 2) το sdi σας στην 2η και 3)\n`I'm 100% \"ready\"!` στην 3η. Παράδειγμα εξόδου από την εκτέλεση της συνάρτησης `about`:\n\n```text\nMichael Jordan\nsdi2300999\nI'm 100% \"ready\"!\n```",
  "hint": "Η παγίδα είναι η τρίτη γραμμή: σκεφτείτε ποιοι χαρακτήρες έχουν ειδική σημασία μέσα\nσε ένα string literal της C και ποιοι μέσα στο format string της `printf`. Τα διπλά\nεισαγωγικά και το `%` χρειάζονται ειδικό χειρισμό, το μονό εισαγωγικό όχι."
 },
 {
  "id": "exam-2024-sep-q2",
  "kind": "exam",
  "title": "Η συνάρτηση what",
  "source": {
   "title": "Εξέταση Σεπτεμβρίου 2024, Θέμα 2",
   "url": "https://progintro.github.io/exams/2024/progintro-exam-sep-24.pdf",
   "years": [
    2024
   ]
  },
  "chapters": [
   17
  ],
  "topics": [
   "searching",
   "arrays"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α17.10",
  "path": "questions/exams/exam-2024-sep-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2024-sep-q2.html",
  "statement": "**Η συνάρτηση what (10 Μονάδες)**\n\n```c\nint what(int *array, int x, int y) {\n  int mid, low = 0, high = y - 1;\n  while (low <= high) {\n    mid = low + (high - low) / 2;\n    printf(\"%d\\n\", mid);\n    if (array[mid] == x) return 1;\n    else if (array[mid] < x) low = mid + 1;\n    else high = mid - 1;\n  }\n  return 0;\n}\n```\n\nΤι κάνει η συνάρτηση `what` (μέχρι 10 λέξεις εξήγηση); Τι θα τυπώσει αν κληθεί με\nορίσματα `{57, 98, 105, 241}, 36, 4`;",
  "hint": "Αναγνωρίστε το μοτίβο: δύο όρια `low`/`high` που πλησιάζουν μεταξύ τους και ένα\nμεσαίο στοιχείο που συγκρίνεται με το `x`. Για την έξοδο, κρατήστε έναν πίνακα με\nτις τιμές `low`, `high`, `mid` σε κάθε επανάληψη και προσέξτε ότι το 36 είναι\nμικρότερο από όλα τα στοιχεία του πίνακα."
 },
 {
  "id": "exam-2024-sep-q3",
  "kind": "exam",
  "title": "Εύρεση μηδενός σε πίνακα",
  "source": {
   "title": "Εξέταση Σεπτεμβρίου 2024, Θέμα 3",
   "url": "https://progintro.github.io/exams/2024/progintro-exam-sep-24.pdf",
   "years": [
    2024
   ]
  },
  "chapters": [
   17,
   15
  ],
  "topics": [
   "searching",
   "complexity",
   "floating-point"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α17.12",
  "path": "questions/exams/exam-2024-sep-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2024-sep-q3.html",
  "statement": "**Εύρεση Μηδενός σε Πίνακα [15 Μονάδες]**\n\nΓράψτε μία συνάρτηση `find_zero` η οποία λαμβάνει ως όρισμα έναν πίνακα από τιμές\n`double` ταξινομημένες σε αύξουσα σειρά και επιστρέφει την θέση (index) όπου υπάρχει\nτο 0 ή -1 αν δεν το βρει. Η συνάρτηση μπορεί να έχει οποιαδήποτε διεπαφή (ορίσματα /\nτύπο επιστροφής) επιθυμείτε. Για παράδειγμα αν δοθεί ο πίνακας\n`{-8.1, -2.3, 0.0, 1.9}` θέλουμε να επιστραφεί η τιμή 2. Αντίστοιχα, αν δοθεί ο\nπίνακας `{1.0}` θέλουμε να επιστραφεί -1. Τι χρονική και χωρική πολυπλοκότητα έχει ο\nαλγόριθμός σας (5/15 της βαθμολογίας);",
  "hint": "Ο πίνακας είναι ταξινομημένος, άρα μια σειριακή αναζήτηση αφήνει βαθμούς στο τραπέζι:\nσκεφτείτε ποιος αλγόριθμος εκμεταλλεύεται τη διάταξη για λογαριθμικό χρόνο. Αφού ο\nπίνακας δεν «ξέρει» το μέγεθός του, η διεπαφή πρέπει να περνά και το πλήθος των\nστοιχείων. Ελέγξτε τις ακραίες περιπτώσεις: πίνακας ενός στοιχείου, μηδέν στην πρώτη ή\nστην τελευταία θέση, όλα θετικά ή όλα αρνητικά."
 },
 {
  "id": "exam-2024-sep-q4",
  "kind": "exam",
  "title": "Μετρητής λέξεων",
  "source": {
   "title": "Εξέταση Σεπτεμβρίου 2024, Θέμα 4",
   "url": "https://progintro.github.io/exams/2024/progintro-exam-sep-24.pdf",
   "years": [
    2024
   ]
  },
  "chapters": [
   9,
   5
  ],
  "topics": [
   "input-output",
   "operators"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α9.31",
  "path": "questions/exams/exam-2024-sep-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2024-sep-q4.html",
  "statement": "**Μετρητής Λέξεων [25 Μονάδες]**\n\nΓράψτε ένα πρόγραμμα `wordcount` το οποίο διαβάζει ένα κείμενο από την πρότυπη είσοδο\n(stdin) και τυπώνει στην πρότυπη έξοδο (stdout) τον αριθμό των λέξεων που διάβασε καθώς\nκαι το μέσο μήκος λέξης του κειμένου με ακρίβεια δύο δεκαδικών ψηφίων. Ως *λέξη*,\nορίζουμε οποιαδήποτε ακολουθία συνεχόμενων χαρακτήρων A-Z, a-z και 0-9 (μετράμε μόνο\nλέξεις με λατινικούς χαρακτήρες) και ως *μήκος* τον αριθμό των συνεχόμενων χαρακτήρων.\nΓια παράδειγμα, το κείμενο \"I'm a good person\" έχει σύνολο 5 λέξεις και μέσο μήκος\n(1 + 1 + 1 + 4 + 6)/5 = 2.6 χαρακτήρες. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ echo \"I'm a good person\" | ./wordcount\nTotal words: 5\nAverage word length: 2.60\n```\n\n```text\n$ cat quote.txt\n\"Success is not final, failure is not fatal: It is the courage to continue that counts.\"\n$ ./wordcount < quote.txt\nTotal words: 16\nAverage word length: 4.25\n```",
  "hint": "Διαβάστε χαρακτήρα-χαρακτήρα μέχρι το `EOF` και κρατήστε μια κατάσταση «είμαι μέσα σε\nλέξη ή όχι»: μια λέξη ξεκινά όταν περνάτε από μη αλφαριθμητικό σε αλφαριθμητικό\nχαρακτήρα. Δεν χρειάζεται να αποθηκεύσετε το κείμενο, μόνο μετρητές. Προσέξτε την\nακέραια διαίρεση στον μέσο όρο και τι θα τυπώσετε αν η είσοδος δεν έχει καμία λέξη."
 },
 {
  "id": "exam-2024-sep-q5",
  "kind": "exam",
  "title": "Αντιστροφή λίστας",
  "source": {
   "title": "Εξέταση Σεπτεμβρίου 2024, Θέμα 5",
   "url": "https://progintro.github.io/exams/2024/progintro-exam-sep-24.pdf",
   "years": [
    2024
   ]
  },
  "chapters": [
   21,
   13,
   15
  ],
  "topics": [
   "linked-lists",
   "dynamic-memory",
   "complexity"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α21.8",
  "path": "questions/exams/exam-2024-sep-q5.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2024-sep-q5.html",
  "statement": "**Αντιστροφή Λίστας [25 Μονάδες]**\n\nΓράψτε μια συνάρτηση `reverse_list` η οποία παίρνει ως όρισμα μια λίστα ακεραίων\nτύπου `List` και επιστρέφει μια νέα λίστα με τους κόμβους της σε αντίστροφη σειρά σε\nσχέση με την αρχική. Για παράδειγμα, αν δοθεί η ακόλουθη λίστα:\n\n```text\n[12|•]──>[99|•]──>[37|•]──>NULL\n```\n\nπεριμένουμε να επιστραφεί η ανεστραμμένη χωρίς παρενέργειες (side-effects) στην αρχική:\n\n```text\n[37|•]──>[99|•]──>[12|•]──>NULL\n```\n\nΠοια είναι η χρονική και η χωρική πολυπλοκότητα του αλγορίθμου σας (8/25 της\nβαθμολογίας); Ο τύπος `List` δίνεται παρακάτω:\n\n```c\ntypedef struct node {\n  int value;\n  struct node * next;\n} * List;\n```",
  "hint": "«Χωρίς παρενέργειες» σημαίνει ότι δεν πειράζετε τους δείκτες `next` της αρχικής\nλίστας: χρειάζεστε νέους κόμβους με `malloc`. Παρατηρήστε ότι αν διατρέξετε την αρχική\nλίστα από την αρχή και εισάγετε κάθε αντίγραφο στην *αρχή* της νέας, η σειρά βγαίνει\nαντεστραμμένη. Σκεφτείτε την κενή λίστα και τι γίνεται αν αποτύχει η `malloc`."
 },
 {
  "id": "exam-2024-sep-q6",
  "kind": "exam",
  "title": "Γεμίζοντας με χρώμα",
  "source": {
   "title": "Εξέταση Σεπτεμβρίου 2024, Θέμα 6",
   "url": "https://progintro.github.io/exams/2024/progintro-exam-sep-24.pdf",
   "years": [
    2024
   ]
  },
  "chapters": [
   25,
   11,
   12
  ],
  "topics": [
   "recursion",
   "multidim-arrays",
   "command-line-args",
   "files"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α25.14",
  "path": "questions/exams/exam-2024-sep-q6.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2024-sep-q6.html",
  "statement": "**Γεμίζοντας με Χρώμα [25 Μονάδες]**\n\nΑν έχετε χρησιμοποιήσει κάποιο πρόγραμμα ζωγραφικής στον υπολογιστή (π.χ., Paint),\nίσως έχετε κάνει χρήση του \"κουβά\", του εργαλείου δηλαδή που μας βοηθάει να γεμίζουμε\nγρήγορα κλειστές επιφάνειες χωρίς εμπόδια. Το Σχήμα 1 δείχνει ένα παράδειγμα:\n\n```text\n πριν         μετά\n......       ......\n..###.       ..###.\n.#..#.  -->  .####.\n.#X.#.       .####.\n.###..       .###..\n......       ......\n```\n\n*Σχήμα 1: Οπτικοποίηση της διαδικασίας γεμίσματος με χρώμα. Στο σχήμα στα αριστερά\nεπιλέξαμε την θέση (3, 2) - 3η γραμμή, 2η στήλη - για να την γεμίσουμε με χρώμα. Στο\nσχήμα στα δεξιά παρατηρούμε το αποτέλεσμα του γεμίσματός μας.*\n\n> Σημείωση: το Σχήμα 1 του πρωτοτύπου είναι πλέγμα 6×6 με χρωματιστά κελιά· εδώ\n> αποδίδεται με `#` για χρωματισμένο κελί και `X` για το σημείο εκκίνησης.\n\nΓια τις ανάγκες της εφαρμογής μας κάνουμε τις εξής παραδοχές: (1) έχουμε μόνο δύο\nχρώματα που αναπαρίστανται με 0 και 1, (2) το πρόγραμμά μας γεμίζει την εικόνα μόνο με\nτο χρώμα 1, (3) οι εικόνες που χειριζόμαστε είναι τετραγωνικές και (4) το χρώμα μπορεί\nμόνο να γεμίζει επιφάνειες που επικοινωνούν ελεύθερα με το αρχικό σημείο κάνοντας μόνο\nκινήσεις πάνω, κάτω, αριστερά, δεξιά (όχι διαγώνια). Εάν ένα κελί περιέχει ήδη το χρώμα\n1, το κελί δεν θεωρείται ελεύθερο και δρα ως \"τοίχος\" για το γέμισμά μας.\n\nΓράψτε ένα πρόγραμμα το οποίο παίρνει ως όρισμα το όνομα του αρχείου που περιέχει την\nεικόνα και το αρχικό σημείο για γέμισμα και τυπώνει στην έξοδο την τελική εικόνα. Η\nπρώτη σειρά του αρχείου περιέχει την διάσταση της εικόνας, η δεύτερη σειρά τις\nσυντεταγμένες του αρχικού σημείου και τέλος ακολουθεί η δισδιάστατη εικόνα. Παράδειγμα\nεκτέλεσης ακολουθεί:\n\n```text\n$ cat picture.txt\n6\n3 2\n000000\n001110\n010010\n010010\n011100\n000000\n$ ./fill picture.txt\n000000\n001110\n011110\n011110\n011100\n000000\n```",
  "hint": "Το γέμισμα είναι φυσικά αναδρομικό: χρωματίζετε ένα ελεύθερο κελί και ζητάτε το ίδιο\nγια τους τέσσερις γείτονές του. Η βασική περίπτωση είναι κελί εκτός ορίων ή κελί που\nέχει ήδη 1, κάτι που εξασφαλίζει και τον τερματισμό. Προσέξτε ότι οι γραμμές του αρχείου\nείναι ψηφία χωρίς κενά και ότι οι συντεταγμένες του παραδείγματος (3, 2) πρέπει να\nαντιστοιχιστούν σωστά σε δείκτες πίνακα (δείτε το σχήμα)."
 },
 {
  "id": "exam-2025-jan-q1",
  "kind": "exam",
  "title": "Mystery",
  "source": {
   "title": "Εξέταση Ιανουαρίου 2025, Θέμα 1",
   "url": "https://progintro.github.io/exams/2025/progintro-exam-jan-25.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   5,
   6
  ],
  "topics": [
   "bitwise",
   "loops",
   "undefined-behavior"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α5.9",
  "path": "questions/exams/exam-2025-jan-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2025-jan-q1.html",
  "statement": "**Mystery [10 Μονάδες]**\n\nΗ συνάρτηση `mystery` δέχεται ως όρισμα έναν ακέραιο αριθμό που αποτελείται από τα 3\nτελευταία ψηφία του sdi σας. Για παράδειγμα, αν ο sdi σας είναι ο sdi2400789 τότε καλούμε\nτην συνάρτηση ως `mystery(789)`. Τι θα τυπώσει η συνάρτηση για τα ψηφία του δικού σας sdi;\nΑν δεν έχετε sdi, επιλέξτε έναν τυχαίο τριψήφιο. Αιτιολογήστε όπου νομίζετε πως χρειάζεται.\n\n```c\nint mystery(int number) {\n  int i;\n  int step = 2;\n  printf(\"%s %d\\n\", \"Starting loop\", i);\n  for(i = 0; i < 3; i++) {\n    printf(\"step %d %d\\n\", i, number + step);\n    step = (step << 2) + 2;\n  }\n  printf(\"Ending loop %d\\n\", i);\n  return number + step;\n}\n```",
  "hint": "Κοιτάξτε προσεκτικά την πρώτη `printf`: τι τιμή έχει το `i` εκείνη τη στιγμή; Για\nτο `step`, θυμηθείτε ότι το `<< 2` πολλαπλασιάζει επί 4, και φτιάξτε έναν πίνακα με\nτις τιμές του `i` και του `step` σε κάθε επανάληψη. Προσέξτε και την τιμή του `i`\nμετά το τέλος του βρόχου."
 },
 {
  "id": "exam-2025-jan-q2",
  "kind": "exam",
  "title": "Η συνάρτηση dog",
  "source": {
   "title": "Εξέταση Ιανουαρίου 2025, Θέμα 2",
   "url": "https://progintro.github.io/exams/2025/progintro-exam-jan-25.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   14,
   13,
   2
  ],
  "topics": [
   "strings",
   "pointer-arithmetic",
   "dynamic-memory"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α14.11",
  "path": "questions/exams/exam-2025-jan-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2025-jan-q2.html",
  "statement": "**Η συνάρτηση dog (10 Μονάδες)**\n\n```c\nchar *dog(const char *str1, const char *str2) {\n    size_t len1 = strlen(str1);\n    size_t len2 = strlen(str2);\n    char *result = malloc(len1 + len2 + 1);\n    if (!result) return NULL;\n    char *ptr = result;\n    while (*str1) *ptr++ = *str1++;\n    while (*str2) *ptr++ = *str2++;\n    *ptr = '\\0';\n    return result;\n}\n```\n\nΤι κάνει η συνάρτηση dog (μέχρι 15 λέξεις εξήγηση); Τι θα τυπώσουν οι παρακάτω εντολές;\n\n```c\nchar arg1[] = {71, 111, 111, 100, 32, 0};\nchar arg2[5] = {'j', 111, 98, '!', 0};\nprintf(\"%s\\n\", dog(arg1, arg2));\n```",
  "hint": "Παρακολουθήστε πού δείχνει ο `ptr` μετά από κάθε βρόχο και γιατί η `malloc` ζητά\n`len1 + len2 + 1` bytes. Για την έξοδο, μετατρέψτε τους αριθμούς σε χαρακτήρες με τον\nπίνακα ASCII (το 0 είναι ο τερματικός χαρακτήρας και το 32 το κενό). Σκεφτείτε επίσης\nτι γίνεται με τη μνήμη που επιστρέφει η `dog` σε αυτή την κλήση."
 },
 {
  "id": "exam-2025-jan-q3",
  "kind": "exam",
  "title": "Κινούμενος Μέσος Όρος - sma",
  "source": {
   "title": "Εξέταση Ιανουαρίου 2025, Θέμα 3",
   "url": "https://progintro.github.io/exams/2025/progintro-exam-jan-25.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   12,
   10
  ],
  "topics": [
   "command-line-args",
   "arrays",
   "floating-point"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α12.21",
  "path": "questions/exams/exam-2025-jan-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2025-jan-q3.html",
  "statement": "**Κινούμενος Μέσος Όρος - sma [25 Μονάδες]**\n\nΟ κινούμενος μέσος όρος είναι παρεμφερής με τον κανονικό μέσο όρο, με μια διαφορά: ο\nκινούμενος μέσος όρος απαιτεί και ένα \"παράθυρο\" (window), δηλαδή τον αριθμό των τιμών\n(μετρώντας από το τέλος) που θέλουμε να λάβουμε υπόψη μας στον υπολογισμό του μέσου\nόρου. Για παράδειγμα, ας υποθέσουμε ότι έχουμε αυτές τις 10 τιμές:\n\n$$9 \\quad 7 \\quad 7 \\quad 1 \\quad 4 \\quad 4 \\quad 4 \\quad 38 \\quad 8 \\quad 4$$\n\nΟ μέσος όρος αυτών των τιμών είναι $\\frac{9+7+7+1+4+4+4+38+8+4}{10} = 8.60$. Για να\nυπολογίσουμε τον κινούμενο μέσο, πρέπει να επιλέξουμε ένα παράθυρο, έστω 3. Τότε ο\nκινούμενος μέσος με παράθυρο 3 για αυτά τα στοιχεία λαμβάνει υπόψη του μόνο τα τελευταία 3:\n\n$$9 \\quad 7 \\quad 7 \\quad 1 \\quad 4 \\quad 4 \\quad 4 \\quad \\underbrace{38 \\quad 8 \\quad 4}_{SMA_3}$$\n\nκαι επομένως $SMA_3 = \\frac{38+8+4}{3} = 16.67$. Αντίστοιχα, μπορούν να οριστούν κινούμενοι\nμέσοι με μικρότερα παράθυρα (π.χ., παράθυρο 1 σημαίνει μόνο το τελευταίο στοιχείο) ή\nμεταλύτερα παράθυρα (π.χ., παράθυρο 10 θα λάμβανε υπόψη του όλες τις τιμές παραπάνω).\nΓράψτε ένα πρόγραμμα που υπολογίζει τον κινούμενο μέσο όρο με παράθυρο 10 ($SMA_{10}$) και\nακρίβεια 2 δεκαδικών ψηφίων για όλους τους ακεραίους που θα δοθούν ως ορίσματα στο\nπρόγραμμα από την γραμμή εντολών. Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ ./sma 42 0 -4 9 7 7 1 4 4 4 38 8 4\nThe simple moving average (window 10) is: 8.60\n```",
  "hint": "Τα ορίσματα βρίσκονται στο `argv` ως συμβολοσειρές, οπότε χρειάζεστε μετατροπή σε\nακέραιο (π.χ. `atoi`), και τα τελευταία 10 είναι στις τελευταίες θέσεις του `argv`:\nυπολογίστε από ποιον δείκτη ξεκινάτε με βάση το `argc`. Αποφασίστε τι κάνετε όταν\nδίνονται λιγότερα από 10 ορίσματα ή κανένα, και διαιρέστε σε `double` για να μη χάσετε\nτα δεκαδικά."
 },
 {
  "id": "exam-2025-jan-q4",
  "kind": "exam",
  "title": "Αθροιστής Δέντρων - sumtree",
  "source": {
   "title": "Εξέταση Ιανουαρίου 2025, Θέμα 4",
   "url": "https://progintro.github.io/exams/2025/progintro-exam-jan-25.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   22,
   21,
   15
  ],
  "topics": [
   "trees",
   "recursion",
   "complexity"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α22.18",
  "path": "questions/exams/exam-2025-jan-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2025-jan-q4.html",
  "statement": "**Αθροιστής Δέντρων - sumtree [20 Μονάδες]**\n\nΓράψτε μια συνάρτηση `sumtree` η οποία παίρνει ως όρισμα ένα δέντρο ακεραίων τύπου\n`Tree` και επιστρέφει το άθροισμα όλων των κόμβων του δέντρου. Για παράδειγμα, για το\nακόλουθο δέντρο:\n\n```mermaid\nflowchart TD\n  N3((\"3\")) --> N4((\"4\"))\n  N3 --> N5((\"5\"))\n  N4 --> N6((\"6\"))\n  N4 --> N7((\"7\"))\n  N5 --> N8((\"8\"))\n  N5 --> N9((\"9\"))\n```\n\n*Σχήμα: το δέντρο του παραδείγματος.*\n\nπεριμένουμε να μας επιστρέψει την τιμή: 42 = 3 + 4 + 5 + 6 + 7 + 8 + 9. Ποια είναι η\nχρονική και η χωρική πολυπλοκότητα του αλγορίθμου σας (6/20 της βαθμολογίας); Ο τύπος\n`Tree` δίνεται παρακάτω:\n\n```c\ntypedef struct node {\n  int value;\n  struct node * left;\n  struct node * right;\n} * Tree;\n```",
  "hint": "Το άθροισμα ενός δέντρου ορίζεται φυσικά αναδρομικά, μέσω των αθροισμάτων του αριστερού\nκαι του δεξιού υποδέντρου. Ξεκινήστε από τη βασική περίπτωση του κενού δέντρου (`NULL`).\nΓια τη χωρική πολυπλοκότητα, σκεφτείτε το βάθος της στοίβας των αναδρομικών κλήσεων στη\nχειρότερη περίπτωση (π.χ. ένα δέντρο σαν λίστα)."
 },
 {
  "id": "exam-2025-jan-q5",
  "kind": "exam",
  "title": "Συνένωση Αλφαριθμητικών - join",
  "source": {
   "title": "Εξέταση Ιανουαρίου 2025, Θέμα 5",
   "url": "https://progintro.github.io/exams/2025/progintro-exam-jan-25.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   14,
   13,
   15
  ],
  "topics": [
   "strings",
   "dynamic-memory",
   "complexity"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α14.21",
  "path": "questions/exams/exam-2025-jan-q5.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2025-jan-q5.html",
  "statement": "**Συνένωση Αλφαριθμητικών - join [20 Μονάδες]**\n\nΓράψτε μία *συνάρτηση* `join` η οποία να λαμβάνει ως ορίσματα έναν πίνακα elements από\nαλφαριθμητικά (strings) και ένα delimiter αλφαριθμητικό (string) και να επιστρέφει ένα νέο\nαλφαριθμητικό με όλα τα αλφαριθμητικά συνενωμένα μεταξύ τους με το αλφαριθμητικό\ndelimiter. Για παράδειγμα, αν δώσουμε ως elements τον πίνακα `{\"hall\", \"oates\"}` και ως\ndelimiter το `\" & \"`, τότε η συνάρτηση θέλουμε να μας επιστρέψει το αλφαριθμητικό\n`\"hall & oates\"`. Αντίστοιχα, αν δώσουμε ως elements τον πίνακα `{\"A\", \"Bing\", \"Boom\"}`\nκαι ως delimiter το `\"Bada\"`, τότε πρέπει να μας επιστρέψει `\"ABadaBingBadaBoom\"`. Η\nσυνάρτηση μπορεί να έχει οποιαδήποτε διεπαφή (τύπο επιστροφής / επιπλέον ορίσματα)\nεπιθυμείτε. Τι χρονική και χωρική πολυπλοκότητα έχει ο αλγόριθμός σας (5/20 της\nβαθμολογίας);",
  "hint": "Η συνάρτηση πρέπει να ξέρει πόσα στοιχεία έχει ο πίνακας, οπότε περάστε το πλήθος ως\nεπιπλέον όρισμα. Υπολογίστε πρώτα το ακριβές μήκος του αποτελέσματος (τα μήκη των\nστοιχείων, `n - 1` φορές τον delimiter και τον τερματικό χαρακτήρα), κάντε μία\n`malloc` και μετά αντιγράψτε κρατώντας έναν δείκτη στο τέλος. Προσέξτε ότι επαναλαμβανόμενη\n`strcat` από την αρχή του αποτελέσματος χαλάει την πολυπλοκότητα, και σκεφτείτε την\nπερίπτωση άδειου πίνακα."
 },
 {
  "id": "exam-2025-jan-q6",
  "kind": "exam",
  "title": "Μετρώντας τα Αστέρια - stars",
  "source": {
   "title": "Εξέταση Ιανουαρίου 2025, Θέμα 6",
   "url": "https://progintro.github.io/exams/2025/progintro-exam-jan-25.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   16,
   18,
   13
  ],
  "topics": [
   "multidim-arrays",
   "files",
   "complexity",
   "dynamic-memory",
   "problem-solving"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α16.26",
  "path": "questions/exams/exam-2025-jan-q6.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2025-jan-q6.html",
  "statement": "**Μετρώντας τα Αστέρια - stars [25 Μονάδες]**\n\nΕίμαστε στην διαδικασία προγραμματισμού του καινούριου διαστημοπλοίου του DI και για την\nλειτουργία του είναι απαραίτητο ένα υποσύστημα που να υπολογίζει το σύνολο των αστεριών σε\nένα τμήμα του ορίζοντα. Το Σχήμα 1 δείχνει ένα παράδειγμα:\n\n|   |   |   |   |   |\n|:-:|:-:|:-:|:-:|:-:|\n| 0 | 3 | 0 | 1 | 0 |\n| 0 | 0 | 0 | 8 | 0 |\n| 0 | **42** | **0** | **0** | 0 |\n| 7 | **1** | **0** | **5** | 4 |\n| 0 | 2 | 0 | 0 | 0 |\n\n*Σχήμα 1: Μετρώντας τα αστέρια σε μια υποπεριοχή του ορίζοντα (πλέγμα 5x5). Ο ακέραιος\nστο κάθε κελί υποδεικνύει έναν αριθμό αστεριών. Στο παράδειγμα επιλέξαμε ένα\nπαραλληλόγραμμο με συντεταγμένες από το (2, 1) (άνω αριστερό άκρο) έως και το (3, 3) (κάτω\nδεξί άκρο). Στην επιλεγμένη περιοχή (με έντονα) το σύνολο των αστεριών είναι 42 + 1 + 5 = 48.*\n\nΘεωρούμε πως ο ορίζοντας είναι ένα τετραγωνικό πλέγμα και πως σε κάθε κελί του υπάρχει\nένας ακέραιος αριθμός από αστέρια. Οι περιοχές που μπορεί να επιλέξει ο χρήστης είναι\nαποκλειστικά παραλληλόγραμμα σε σχήμα, τα οποία προσδιορίζονται από τις συντεταγμένες της\nάνω αριστερής και κάτω δεξιάς γωνίας τους.\n\nΓράψτε ένα πρόγραμμα το οποίο παίρνει ως όρισμα το όνομα αρχείου που περιέχει την διάσταση\nτου πλέγματος καθώς και τους αριθμούς των αστεριών ανά κελί. Στην συνέχεια, το πρόγραμμά\nσας πρέπει να διαβάζει από την πρότυπη είσοδο (stdin) τις συντεταγμένες του χρήστη και να\nυπολογίζει τον αριθμό αστεριών *αποδοτικά* για κάθε περιοχή που θα ζητηθεί. Το πρόγραμμά\nσας πρέπει να είναι σε θέση να απαντάει σε επαναλαμβανόμενες ερωτήσεις από τον χρήση μέχρι\nνα λάβει EOF. Αν η διάσταση του πλέγματος είναι Ν και ο αριθμός των ερωτήσεων του χρήστη\nείναι Q, ποια η χρονική και χωρική πολυπλοκότητα της λύσης σας (8/25 της βαθμολογίας);\nΠαράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ cat horizon.txt\n5\n0 3 0 1 0\n0 0 0 8 0\n0 42 0 0 0\n7 1 0 5 4\n0 2 0 0 0\n$ ./stars horizon.txt\nProvide top-left x, y coordinates: 2 1\nProvide bottom-right x, y coordinates: 3 3\nTotal number of stars in region (2, 1) - (3, 3) is 48\nProvide top-left x, y coordinates: 0 0\nProvide bottom-right x, y coordinates: 4 4\nTotal number of stars in region (0, 0) - (4, 4) is 73\nProvide top-left x, y coordinates: 3 0\nProvide bottom-right x, y coordinates: 3 0\nTotal number of stars in region (3, 0) - (3, 0) is 7\nProvide top-left x, y coordinates: Terminating\n```",
  "hint": "Από το παράδειγμα, η πρώτη συντεταγμένη είναι η γραμμή και η δεύτερη η στήλη. Αν\nαθροίζετε κάθε περιοχή κελί προς κελί, κάθε ερώτηση κοστίζει O(N²): σκεφτείτε ποια\nπληροφορία μπορείτε να προϋπολογίσετε μία φορά μετά το διάβασμα του αρχείου ώστε κάθε\nερώτηση να απαντιέται με λίγες πράξεις (χρόνος έναντι μνήμης). Δεσμεύστε το πλέγμα\nδυναμικά αφού διαβάσετε το N, και χρησιμοποιήστε την τιμή επιστροφής της `scanf` για\nνα σταματήσετε στο EOF."
 },
 {
  "id": "exam-2025-sep-q1",
  "kind": "exam",
  "title": "Mystery",
  "source": {
   "title": "Εξέταση Σεπτεμβρίου 2025, Θέμα 1",
   "url": "https://progintro.github.io/exams/2025/progintro-exam-sep-25.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   6,
   2
  ],
  "topics": [
   "loops",
   "variables",
   "undefined-behavior"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α6.18",
  "path": "questions/exams/exam-2025-sep-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2025-sep-q1.html",
  "statement": "**Mystery [10 Μονάδες]**\n\nΗ συνάρτηση `mystery` δέχεται ως όρισμα έναν ακέραιο αριθμό που αποτελείται από τα 3\nτελευταία ψηφία του sdi σας. Για παράδειγμα, αν ο sdi σας είναι ο sdi2400789 τότε καλούμε\nτην συνάρτηση ως `mystery(789)`. Τι θα τυπώσει η συνάρτηση για τα ψηφία του δικού σας sdi;\nΑν δεν έχετε sdi, επιλέξτε έναν τυχαίο τριψήφιο. Αιτιολογήστε όπου νομίζετε πως χρειάζεται.\n\n```c\nint mystery(int number) {\n  int s = 0, rem;\n  printf(\"%s %d %d\\n\", \"Starting loop\", s, rem);\n  do {\n    rem = number % 10;\n    printf(\"Inner: %d\\n\", rem);\n    number /= 10;\n    s += rem;\n  } while (number);\n  printf(\"Loop ended %d\\n\", s);\n  return s;\n}\n```",
  "hint": "Κρατήστε έναν πίνακα με τις τιμές των `number`, `rem` και `s` σε κάθε επανάληψη\nκαι θυμηθείτε ότι το σώμα της `do-while` εκτελείται τουλάχιστον μία φορά. Προσέξτε\nιδιαίτερα την πρώτη `printf`: ποια τιμή έχει το `rem` εκείνη τη στιγμή; Σκεφτείτε\nεπίσης τι γίνεται αν το τριψήφιό σας ξεκινά με 0 (π.χ. 042)."
 },
 {
  "id": "exam-2025-sep-q2",
  "kind": "exam",
  "title": "Η συνάρτηση transform",
  "source": {
   "title": "Εξέταση Σεπτεμβρίου 2025, Θέμα 2",
   "url": "https://progintro.github.io/exams/2025/progintro-exam-sep-25.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   14,
   12
  ],
  "topics": [
   "strings",
   "pointer-arithmetic",
   "pointers"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α14.12",
  "path": "questions/exams/exam-2025-sep-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2025-sep-q2.html",
  "statement": "**Η συνάρτηση transform (15 Μονάδες)**\n\n```c\nchar *transform(char * str) {\n    int length = strlen(str);\n    char * lo = str;\n    char * hi = str + length - 1;\n    char tmp;\n    while (lo < hi) {\n      tmp = *lo;\n      *lo++ = *hi;\n      *hi-- = tmp;\n    }\n    return str;\n}\n```\n\nΤι κάνει η συνάρτηση transform (μέχρι 15 λέξεις εξήγηση); Τι θα τυπωθεί κατά την εκτέλεση\nτων δύο ακόλουθων εντολών;\n\n```c\n    char arg[] = {'!', 121, 107, 99, 117, 76, 0};\n    printf(\"%s\\n\", transform(arg));\n```\n\n> Σημείωση: στο τέλος της εξέτασης δίνεται πίνακας ASCII ως βοήθημα.",
  "hint": "Παρακολουθήστε πώς κινούνται οι δείκτες `lo` και `hi` και τι ανταλλάσσουν σε κάθε\nεπανάληψη, και πότε σταματά ο βρόχος. Για την έξοδο, μετατρέψτε πρώτα κάθε αριθμό του\n`arg` σε χαρακτήρα με τον πίνακα ASCII· το `0` στο τέλος είναι ο τερματικός χαρακτήρας."
 },
 {
  "id": "exam-2025-sep-q3",
  "kind": "exam",
  "title": "Μέση Τιμή Τυχαίων Μεταβλητών - mean",
  "source": {
   "title": "Εξέταση Σεπτεμβρίου 2025, Θέμα 3",
   "url": "https://progintro.github.io/exams/2025/progintro-exam-sep-25.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   12,
   2
  ],
  "topics": [
   "command-line-args",
   "floating-point",
   "loops"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α12.15",
  "path": "questions/exams/exam-2025-sep-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2025-sep-q3.html",
  "statement": "**Μέση Τιμή Τυχαίων Μεταβλητών - mean [25 Μονάδες]**\n\nΓια μια τυχαία μεταβλητή $X$ που παίρνει τις τιμές $x_1, x_2, \\ldots, x_n$, με αντίστοιχες πιθανότητες\n$p_1, p_2, \\ldots, p_n$, η μέση τιμή $E[X]$ ορίζεται ως:\n\n$$E[X] = \\sum_{i=1}^{n} x_i \\cdot p_i = p_1 \\cdot x_1 + p_2 \\cdot x_2 + \\cdots + x_n \\cdot p_n$$\n\nΓράψτε ένα πρόγραμμα το οποίο παίρνει τις ακέραιες τιμές $x_i$ μιας τυχαίας μεταβλητής\n$X$ μαζί με τις πιθανότητες $p_i$ σε δεκαδική μορφή ($0 \\le p_i \\le 1$) και υπολογίζει την μέση τιμή με\nακρίβεια 8 δεκαδικών ψηφίων. Τα ορίσματα θα δίνονται ως εξής: το κάθε $x_i$ θα ακολουθείται\nαπό το $p_i$ που του αντιστοιχεί. Για παράδειγμα, αν $x_1 = 10$, $p_1 = 0.5$, $x_2 = 20$, $p_2 = 0.3$,\n$x_3 = 40$, $p_3 = 0.20$ ($E[X] = 10 \\cdot 0.5 + 20 \\cdot 0.3 + 40 \\cdot 0.20 = 19.0$) το πρόγραμμα καλείται ως εξής:\n\n```text\n$ ./mean 10 0.5 20 0.30 40 0.20\nThe mean of the random variable is: 19.00000000\n```\n\nΌλα τα ορίσματα δίνονται από την γραμμή εντολών και το αποτέλεσμα δεν είναι ανάγκη να\nείναι ακέραιο (ακολουθεί παράδειγμα).\n\n```text\n./mean 42 0.222 5 0.0009999 100 0.777 100000 0.0000001\nThe mean of the random variable is: 87.03899950\n```",
  "hint": "Διατρέξτε το `argv` ανά ζεύγη (τιμή, πιθανότητα), μετατρέποντας το πρώτο σε ακέραιο\nκαι το δεύτερο σε `double` (π.χ. με `atoi`/`atof` ή `strtol`/`strtod`). Σκεφτείτε\nτι πρέπει να γίνει αν το πλήθος των ορισμάτων δεν είναι άρτιο ή είναι μηδέν, και\nχρησιμοποιήστε `%.8f` για την έξοδο."
 },
 {
  "id": "exam-2025-sep-q4",
  "kind": "exam",
  "title": "Μεσαίο Στοιχείο Λίστας",
  "source": {
   "title": "Εξέταση Σεπτεμβρίου 2025, Θέμα 4",
   "url": "https://progintro.github.io/exams/2025/progintro-exam-sep-25.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   21,
   15,
   13
  ],
  "topics": [
   "linked-lists",
   "complexity",
   "dynamic-memory"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α21.9",
  "path": "questions/exams/exam-2025-sep-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2025-sep-q4.html",
  "statement": "**Μεσαίο Στοιχείο Λίστας [25 Μονάδες]**\n\nΓράψτε μια συνάρτηση `middle_element` η οποία παίρνει ως όρισμα μια λίστα ακεραίων\nτύπου `List` και επιστρέφει μια νέα λίστα με μοναδικό στοιχείο το μεσαίο στοιχείο της λίστας.\nΑν ο αριθμός των στοιχείων είναι άρτιος, μπορεί να επιστραφεί οποιοδήποτε από τα μεσαία\nστοιχεία. Για παράδειγμα, αν δοθεί η ακόλουθη λίστα:\n\n```text\n12 -> 99 -> 42 -> 3 -> 17 -> NULL\n```\n\nπεριμένουμε να επιστραφεί η ακόλουθη λίστα:\n\n```text\n42 -> NULL\n```\n\nΠοια είναι η χρονική και η χωρική πολυπλοκότητα του αλγορίθμου σας (8/25 της βαθμολογίας);\nΟ τύπος `List` δίνεται παρακάτω:\n\n```c\ntypedef struct node {\n  int value;\n  struct node * next;\n} * List;\n```\n\n**Bonus**: Αν ο αλγόριθμός σας βρίσκει το μεσαίο στοιχείο της λίστας χωρίς να την διατρέξει\nπάνω από μία φορές.",
  "hint": "Η απλή λύση μετρά πρώτα τους κόμβους και μετά ξαναπερπατά ως τη μέση· για το bonus,\nσκεφτείτε δύο δείκτες που ξεκινούν μαζί αλλά προχωρούν με διαφορετική ταχύτητα.\nΜην ξεχάσετε ότι πρέπει να επιστραφεί **νέα** λίστα (ένας νέος κόμβος με `malloc`),\nκαι ελέγξτε τι επιστρέφετε για κενή λίστα ή λίστα ενός στοιχείου."
 },
 {
  "id": "exam-2025-sep-q5",
  "kind": "exam",
  "title": "Το Καλό το Μονοπάτι - path",
  "source": {
   "title": "Εξέταση Σεπτεμβρίου 2025, Θέμα 5",
   "url": "https://progintro.github.io/exams/2025/progintro-exam-sep-25.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   25,
   12,
   18
  ],
  "topics": [
   "dynamic-programming",
   "multidim-arrays",
   "files"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α25.15",
  "path": "questions/exams/exam-2025-sep-q5.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2025-sep-q5.html",
  "statement": "**Το Καλό το Μονοπάτι - path [25 Μονάδες]**\n\nΣτην προσπάθειά του να τονώσει την τουριστική κίνηση, ο Ελληνικός Ορειβατικός Σύλλογος (ΕΟΣ)\nαποφάσισε να χρηματοδοτήσει ένα καινούριο έργο για την δημιουργία νέων, ήσσονος προσπαθείας\nμονοπατιών που να απευθύνονται σε αρχαρίους. Ο ΕΟΣ έχει ήδη πρόσβαση σε αναλυτικούς χάρτες\nμε την δυσκολία της κάθε υποδιαδρομής. Το μόνο που λείπει για να προχωρήσει στην χάραξη των\nμονοπατιών, είναι ένα σύστημα το οποίο δοθέντος ενός χάρτη να υπολογίζει εύκολα και γρήγορα\nτο μονοπάτι ελαχίστου κόστους. Ως συνήθως, το τμήμα μας προσφέρθηκε να βοηθήσει—αμισθί\nεννοείται—για την ταχεία διεκπεραίωση του έργου. Το Σχήμα 1 δείχνει έναν χάρτη-παράδειγμα\nαπό το φαράγγι του Βίκου:\n\n| | | | | |\n|---|---|---|---|---|\n| **[10]** | 13 | 10 | 11 | 10 |\n| **[10]** | 10 | 10 | 18 | 10 |\n| **[15]** | 42 | 42 | 42 | 42 |\n| **[17]** | **[5]** | **[5]** | **[5]** | 14 |\n| 10 | 10 | 10 | **[10]** | **[10]** |\n\n*Σχήμα 1: Ένας 5x5 χάρτης του ΕΟΣ με τα κόστη κάθε υποδιαδρομής να φαίνονται σε κάθε\nκελί του πλέγματος. Η διαδρομή ελαχίστου κόστους εικονίζεται σκιαγραφημένη. Παρατηρήστε\nπως η διαδρομή αποφεύγει τα κελιά υψηλού κόστους (τα 42 αναπαριστούν τον Βοϊδομάτη).*\n\n> Σημείωση: στο πρωτότυπο η διαδρομή είναι χρωματισμένα κελιά· εδώ σημειώνεται με `[ ]`.\n\nΘεωρούμε πως όλοι οι χάρτες του ΕΟΣ είναι ένα τετραγωνικό πλέγμα και πως σε κάθε\nκελί του υπάρχει ένας ακέραιος αριθμός που αναπαριστά το κόστος της κάθε υποδιαδρομής.\nΓια λόγους απλοποίησης, θεωρούμε πως σε κάθε χάρτη ο στόχος είναι να χαράξουμε ένα\nμονοπάτι από την άνω αριστερή γωνία του χάρτη μέχρι την κάτω δεξιά. Επίσης, κατά την\nδιάρκεια της χάραξης επιτρέπονται μόνο μονοπάτια τα οποία κινούνται προς τα κάτω ή προς\nτα δεξιά (όχι προς τα πάνω / αριστερά / διαγώνια).\n\nΓράψτε ένα πρόγραμμα το οποίο παίρνει ως όρισμα το όνομα του αρχείου που περιέχει\nτον χάρτη (διάσταση καθώς και τα κόστη κάθε υποδιαδρομής) και υπολογίζει το μονοπάτι\nελαχίστου κόστους. Αν η διάσταση του πλέγματος είναι Ν, ποια η χρονική και χωρική\nπολυπλοκότητα της λύσης σας (8/25 της βαθμολογίας); Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ cat map.txt\n5\n10 13 10 11 10\n10 10 10 18 10\n15 42 42 42 42\n17  5  5  5 14\n10 10 10 10 10\n$ ./path map.txt\nMinimum Cost: 87\nMinimum Cost Path: 10 -> 10 -> 15 -> 17 -> 5 -> 5 -> 5 -> 10 -> 10\n```",
  "hint": "Η εξαντλητική αναδρομή δοκιμάζει εκθετικά πολλά μονοπάτια· παρατηρήστε ότι το ελάχιστο\nκόστος για να φτάσετε σε ένα κελί εξαρτάται μόνο από το κελί από πάνω και το κελί από\nαριστερά, οπότε μπορείτε να γεμίσετε έναν πίνακα `N×N` γραμμή-γραμμή (δυναμικός\nπρογραμματισμός). Για να τυπώσετε και το μονοπάτι, ξεκινήστε από την κάτω δεξιά γωνία\nκαι ακολουθήστε προς τα πίσω από πού ήρθε κάθε ελάχιστο. Το `N` διαβάζεται από το αρχείο,\nάρα ο πίνακας χρειάζεται δυναμική δέσμευση· προσέξτε και την πρώτη γραμμή/στήλη."
 },
 {
  "id": "exam-2026-jan-q1",
  "kind": "exam",
  "title": "Mystery",
  "source": {
   "title": "Εξέταση Ιανουαρίου 2026, Θέμα 1",
   "url": "https://progintro.github.io/exams/2026/progintro-exam-jan-26.pdf",
   "years": [
    2026
   ]
  },
  "chapters": [
   5,
   6
  ],
  "topics": [
   "bitwise",
   "operators",
   "loops"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α5.10",
  "path": "questions/exams/exam-2026-jan-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2026-jan-q1.html",
  "statement": "**Mystery [10 Μονάδες]**\n\nΗ συνάρτηση `mystery` δέχεται ως όρισμα έναν ακέραιο αριθμό που αποτελείται από τα 3\nτελευταία ψηφία του sdi σας. Για παράδειγμα, αν ο sdi σας είναι ο sdi2500789 τότε καλούμε\nτην συνάρτηση ως `mystery(789)`. Τι θα τυπώσει η συνάρτηση για τα ψηφία του δικού σας sdi;\nΑν δεν έχετε sdi, επιλέξτε έναν τυχαίο τριψήφιο. Αιτιολογήστε όπου νομίζετε πως χρειάζεται.\n\n```c\nint mystery(int number) {\n  int seed = number % 10;\n  int count = (seed == 0 || seed > 4) ? 2 : seed;\n  printf(\"Seed %d, count: %d\\n\", seed, count);\n  for(int i = 0; i < count; ++i) {\n    printf(\"Loop %d: %d\\n\", i, ++seed);\n    seed &= 0xF;\n  }\n  printf(\"Result: %d\\n\", seed);\n  return seed;\n}\n```",
  "hint": "Μόνο το τελευταίο ψηφίο μετράει· βρείτε πρώτα τι κάνει ο τελεστής συνθήκης `?:` για\nτο `count`. Προσέξτε ότι το `++seed` αυξάνει την τιμή *πριν* τυπωθεί, και ότι το\n`& 0xF` κρατά μόνο τα 4 χαμηλότερα bit: τι γίνεται όταν το `seed` φτάσει το 16;"
 },
 {
  "id": "exam-2026-jan-q2",
  "kind": "exam",
  "title": "Η συνάρτηση compute",
  "source": {
   "title": "Εξέταση Ιανουαρίου 2026, Θέμα 2",
   "url": "https://progintro.github.io/exams/2026/progintro-exam-jan-26.pdf",
   "years": [
    2026
   ]
  },
  "chapters": [
   17,
   13,
   12
  ],
  "topics": [
   "sorting",
   "dynamic-memory",
   "memory-model"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α17.13",
  "path": "questions/exams/exam-2026-jan-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2026-jan-q2.html",
  "statement": "**Η συνάρτηση compute (15 Μονάδες)**\n\n```c\nint *compute(const int *a, size_t na, const int *b, size_t nb) {\n    size_t i = 0, j = 0, k = 0;\n    int * out = malloc((na + nb) * sizeof(int));\n    while (i < na && j < nb) {\n        if (a[i] <= b[j])\n            out[k++] = a[i++];\n        else\n            out[k++] = b[j++];\n    }\n    while (i < na)\n        out[k++] = a[i++];\n    while (j < nb)\n        out[k++] = b[j++];\n    return out;\n}\n```\n\n1. Τι κάνει η συνάρτηση compute (μέχρι 15 λέξεις εξήγηση);\n2. Ποιο θα είναι το περιεχόμενο της μεταβλητής result μετά την εκτέλεση της παρακάτω\n   ακολουθίας εντολών και σε ποια κατηγορία μνήμης είναι αποθηκευμένο;\n\n   ```c\n   int arg1[] = {71, 111, 111, 100, 32, 0};\n   int arg2[5] = {'j', 111, 98, '!', 0};\n   int * result = compute(arg1, 3, arg2, 2);\n   ```\n\n3. Υπάρχει κάποιο σφάλμα στην συνάρτηση compute; Αιτιολογήστε την απάντησή σας.\n\nΣτο τέλος του φυλλαδίου δίνεται πίνακας ASCII ως βοήθημα.",
  "hint": "Δείτε το βήμα που επαναλαμβάνεται: συγκρίνει τα δύο \"τρέχοντα\" στοιχεία και παίρνει το\nμικρότερο· σε ποιον αλγόριθμο ταξινόμησης είναι αυτό το βασικό βήμα και τι υποθέτει για\nτις εισόδους; Για το `result` προσέξτε ότι χρησιμοποιούνται μόνο τα πρώτα `na` και `nb`\nστοιχεία, και ξεχωρίστε πού ζει ο δείκτης από πού ζουν τα δεδομένα στα οποία δείχνει. Για\nτο σφάλμα, σκεφτείτε τι μπορεί να επιστρέψει η `malloc`."
 },
 {
  "id": "exam-2026-jan-q3",
  "kind": "exam",
  "title": "Εύρεση Πρώτων Παραγόντων - factor",
  "source": {
   "title": "Εξέταση Ιανουαρίου 2026, Θέμα 3",
   "url": "https://progintro.github.io/exams/2026/progintro-exam-jan-26.pdf",
   "years": [
    2026
   ]
  },
  "chapters": [
   6,
   4
  ],
  "topics": [
   "math-algorithms",
   "loops",
   "command-line-args"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α6.25",
  "path": "questions/exams/exam-2026-jan-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2026-jan-q3.html",
  "statement": "**Εύρεση Πρώτων Παραγόντων - factor [25 Μονάδες]**\n\nΚάθε φυσικός αριθμός μπορεί να γραφεί ως το γινόμενο των πρώτων παραγόντων του. Για\nπαράδειγμα, ο αριθμός 42 μπορεί να γραφεί ως 2 · 3 · 7. Γράψτε ένα πρόγραμμα το οποίο\nπαίρνει έναν θετικό ακέραιο ως το πρώτο όρισμα στην γραμμή εντολών και τυπώνει στην\nέξοδο όλους τους πρώτους παράγοντές του. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ ./factor 42\nFactors of 42: 2 3 7\n$ ./factor 54\nFactors of 54: 2 3 3 3\n```",
  "hint": "Δοκιμάστε διαιρέτες από το 2 και πάνω και, όσο ένας διαιρέτης διαιρεί τον αριθμό,\nτυπώστε τον και διαιρέστε· έτσι οι επαναλαμβανόμενοι παράγοντες (όπως το 3 στο 54)\nβγαίνουν σωστά και δεν χρειάζεται ξεχωριστός έλεγχος πρώτου. Σκεφτείτε πότε μπορείτε να\nσταματήσετε νωρίτερα (`d * d > n`), καθώς και τι γίνεται αν λείπει το όρισμα ή δεν\nείναι θετικός ακέραιος (π.χ. 0, 1, αρνητικός)."
 },
 {
  "id": "exam-2026-jan-q4",
  "kind": "exam",
  "title": "Διερμηνέας Αριθμητικών Εκφράσεων - eval",
  "source": {
   "title": "Εξέταση Ιανουαρίου 2026, Θέμα 4",
   "url": "https://progintro.github.io/exams/2026/progintro-exam-jan-26.pdf",
   "years": [
    2026
   ]
  },
  "chapters": [
   22,
   15,
   20
  ],
  "topics": [
   "trees",
   "recursion",
   "complexity",
   "unions-enums"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α22.20",
  "path": "questions/exams/exam-2026-jan-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2026-jan-q4.html",
  "statement": "**Διερμηνέας Αριθμητικών Εκφράσεων - eval [25 Μονάδες]**\n\nΓράψτε μια συνάρτηση `eval` η οποία παίρνει ως όρισμα ένα δέντρο ακεραίων εκφράσεων\nτύπου `Expr` και επιστρέφει το αποτέλεσμα της αποτίμησης της έκφρασης. Για παράδειγμα,\nγια την έκφραση (2 + 4) * 21 / 3 το δέντρο έκφρασης δείχνει ως εξής:\n\n```mermaid\ngraph TD\n  D[\"/\"] --> M[\"*\"]\n  D --> T3[\"3\"]\n  M --> P[\"+\"]\n  M --> V21[\"21\"]\n  P --> V2[\"2\"]\n  P --> V4[\"4\"]\n```\n\nκαι αν δοθεί στην συνάρτηση eval, περιμένουμε να μας επιστραφεί η τιμή: 42 = (2 + 4) * 21 / 3.\n\n1. Ποια είναι η χρονική και η χωρική πολυπλοκότητα του αλγορίθμου σας; (8/25)\n2. Ποιον αλγόριθμο διάσχισης επιλέξατε και γιατί; (2/25)\n\nΟ ορισμός του τύπου `Expr` δίνεται παρακάτω:\n\n```c\ntypedef enum {\n  VALUE,  // current node is an integer value\n  ADD,    // current node is addition of two nodes\n  SUB,    // current node is subtraction of left minus right\n  MUL,    // current node is the multiplication of two nodes\n  DIV     // current node is the division of left by right\n} exp_type;\n\ntypedef struct node {\n  exp_type type;\n  int value;\n  struct node * left;\n  struct node * right;\n} * Expr;\n```",
  "hint": "Η φυσική λύση είναι αναδρομική: ένας κόμβος `VALUE` είναι η βάση της αναδρομής, ενώ\nγια έναν τελεστή πρέπει πρώτα να ξέρετε τις τιμές *και των δύο* παιδιών· ποια διάσχιση\n(preorder, inorder, postorder) αντιστοιχεί σε αυτή τη σειρά; Ένα `switch` στο `type`\nταιριάζει καλά. Για την πολυπλοκότητα σκεφτείτε πόσες φορές επισκέπτεστε κάθε κόμβο και\nπόσο βαθιά μπορεί να φτάσει η στοίβα κλήσεων· μην ξεχάσετε τη διαίρεση με το μηδέν και\nτον δείκτη `NULL`."
 },
 {
  "id": "exam-2026-jan-q5",
  "kind": "exam",
  "title": "Περικύκλωση - encirclement",
  "source": {
   "title": "Εξέταση Ιανουαρίου 2026, Θέμα 5",
   "url": "https://progintro.github.io/exams/2026/progintro-exam-jan-26.pdf",
   "years": [
    2026
   ]
  },
  "chapters": [
   25,
   12,
   22
  ],
  "topics": [
   "graphs",
   "multidim-arrays",
   "input-validation",
   "complexity"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α25.16",
  "path": "questions/exams/exam-2026-jan-q5.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2026-jan-q5.html",
  "statement": "**Περικύκλωση - encirclement [25 Μονάδες]**\n\nΣε πολλά παιχνίδια στρατηγικής η περικύκλωση του αντιπάλου αφαιρεί τις δυνατότητες\nκίνησής του και πολύ συχνά οδηγεί σε γρήγορη νίκη. Πότε είναι όμως περικυκλωμένο ένα\nπιόνι του αντιπάλου; Το Σχήμα 1 δείχνει ένα παράδειγμα:\n\n|        | A | B | C | D | E | F | G | H | I | J |\n| ------ | - | - | - | - | - | - | - | - | - | - |\n| **10** |   | O | O | O |   |   |   |   |   |   |\n| **9**  | O |   |   |   | O |   |   |   |   |   |\n| **8**  | O |   | X |   | O |   |   |   |   |   |\n| **7**  | O |   |   |   |   | O | O | O |   |   |\n| **6**  |   | O | O | O |   |   | X |   | O |   |\n| **5**  |   |   |   |   | O |   | X |   | O |   |\n| **4**  |   |   | O |   | X | O | O | O | O |   |\n| **3**  |   | O | X | O |   |   |   |   |   |   |\n| **2**  |   |   | O |   |   | O |   |   |   |   |\n| **1**  |   |   |   |   | O | X | O |   |   |   |\n\nΣχήμα 1: Τα πιόνια του μαύρου (X) στις θέσεις C3, C8, G5, G6 είναι περικυκλωμένα, ενώ\nστις θέσεις F1, E4 είναι ελεύθερα καθώς έχουν διέξοδο προς τα άκρα του πλέγματος.\n\nΘεωρούμε πως ο χάρτης του παιχνιδιού είναι ένα τετραγωνικό πλέγμα και πως κάθε κελί:\n(1) είτε περιέχει μαύρα πιόνια (X), (2) είτε περιέχει λευκά πιόνια (O), (3) είτε είναι\nκενό (.). Ένα πιόνι θεωρείται περικυκλωμένο όταν δεν υπάρχει σειρά κινήσεων πάνω, κάτω,\nαριστερά, δεξιά (δεν επιτρέπονται διαγώνιες κινήσεις) που να επιτρέπει στο πιόνι να\nφτάσει στο άκρο του πλέγματος κινούμενο μόνο σε άδεια κελιά ή κελιά που περιέχουν το\nίδιο χρώμα.\n\nΓράψτε ένα πρόγραμμα το οποίο διαβάζει από την πρότυπη είσοδο (stdin) την διάσταση του\nπλέγματος και τα περιεχόμενα του χάρτη και τυπώνει στην πρότυπη έξοδο (stdout) για το\nκάθε μαύρο πιόνι αν είναι ελεύθερο ή όχι. Το πρόγραμμά σας πρέπει να είναι όσο πιο\nαποδοτικό γίνεται και να μπορεί να διαχειριστεί περιπτώσεις σφάλματος.\n\nΠοια είναι η χρονική και η χωρική πολυπλοκότητα του αλγορίθμου σας; (8/25)\n\nΠαράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ cat map.txt\n10\n. . . . O X O . . .\n. . O . . O . . . .\n. O X O . . . . . .\n. . O . X O O O O .\n. . . . O . X . O .\n. O O O . . X . O .\nO . . . . O O O . .\nO . X . O . . . . .\nO . . . O . . . . .\n. O O O . . . . . .\n$ ./encirclement < map.txt\nThe following pawns are free: F1, E4\nThe following pawns are encircled: C3, G5, G6, C8\n```",
  "hint": "Αντί να ψάχνετε ξεχωριστά έξοδο για κάθε πιόνι, αντιστρέψτε το πρόβλημα: ξεκινήστε από\nόλα τα διαβατά κελιά (κενά ή X) του περιγράμματος και σημαδέψτε με flood fill (DFS ή BFS,\nμε σημάδι \"επισκέφθηκα\") ό,τι φτάνετε κινούμενοι μόνο οριζόντια και κάθετα· όσα X δεν\nσημαδεύτηκαν είναι περικυκλωμένα. Συγκρίνετε το αρχείο με το Σχήμα 1: η πρώτη γραμμή του χάρτη\nστο αρχείο είναι η γραμμή 1 του σχήματος, και η έξοδος παρατάσσει τα πιόνια με αυτή τη σειρά. Ελέγξτε μη έγκυρη\nδιάσταση, λάθος χαρακτήρες και λιγότερα κελιά από όσα περιμένετε."
 },
 {
  "id": "exam-2026-jan-q6",
  "kind": "exam",
  "title": "Ο Στέργιος Ξαναχτυπά",
  "source": {
   "title": "Εξέταση Ιανουαρίου 2026, Θέμα 6",
   "url": "https://progintro.github.io/exams/2026/progintro-exam-jan-26.pdf",
   "years": [
    2026
   ]
  },
  "chapters": [
   11,
   13
  ],
  "topics": [
   "pointers",
   "undefined-behavior",
   "memory-model"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α11.22",
  "path": "questions/exams/exam-2026-jan-q6.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2026-jan-q6.html",
  "statement": "**Ο Στέργιος Ξαναχτυπά [10 Μονάδες]**\n\nΟ Στέργιος κουράστηκε με τους μαθηματικούς γρίφους και αποφάσισε να ασχοληθεί με κώδικα\nσυστημάτων. Ο μπαμπάς του—ο Μάκης—του έδωσε το ακόλουθο κομμάτι κώδικα:\n\n```c\n#include <stdio.h>\n\nint main(void) {\n    char *p1 = NULL;\n    char *p2 = NULL;\n    int n = 16;\n    while (n-- > 0) {\n        if (*p1++ != *p2++) {\n            printf(\"Not Equal\\n\");\n        }\n    }\n    printf(\"Equal\\n\");\n    return 0;\n}\n```\n\nΤι θα κάνει το παραπάνω κομμάτι κώδικα; Θα τυπώσει Equal, Not Equal, δεν κάνει compile,\nθα έχει κάποιο runtime error ή δεν μπορούμε να γνωρίζουμε; Αιτιολογήστε την απάντησή\nσας. Μη σωστά αιτιολογημένες απαντήσεις δεν θα λάβουν βαθμολογία.",
  "hint": "Ξεκινήστε από το ερώτημα αν ο κώδικας περνάει από τον compiler: είναι συντακτικά σωστός;\nΜετά σκεφτείτε τι σημαίνει να διαβάσετε μέσω `*p1` όταν ο `p1` είναι `NULL`, τι λέει\nτο πρότυπο της C γι' αυτό και τι συμβαίνει συνήθως στην πράξη. Αναρωτηθείτε επίσης αν ο\ncompiler (π.χ. με `-O2`) έχει δικαίωμα να υποθέσει κάτι για έναν κώδικα που θα ήταν\nαπροσδιόριστη συμπεριφορά."
 },
 {
  "id": "exam-2026-jun-q1",
  "kind": "exam",
  "title": "Η συνάρτηση mystery",
  "source": {
   "title": "Εξέταση Ιουνίου 2026, Θέμα 1",
   "url": "https://progintro.github.io/exams/2026/progintro-exam-jun-26.pdf",
   "years": [
    2026
   ]
  },
  "chapters": [
   5,
   6
  ],
  "topics": [
   "bitwise",
   "loops",
   "types"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α5.11",
  "path": "questions/exams/exam-2026-jun-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2026-jun-q1.html",
  "statement": "**Η Συνάρτηση mystery (15 Μονάδες)**\n\nΗ συνάρτηση `mystery` δέχεται ως όρισμα έναν ακέραιο αριθμό που αποτελείται από τα 3\nτελευταία ψηφία του sdi σας. Για παράδειγμα, αν ο sdi σας είναι ο sdi2500789 τότε καλούμε\nτην συνάρτηση ως `mystery(789)`. Τι θα τυπώσει η συνάρτηση για τα ψηφία του δικού σας sdi;\nΑν δεν έχετε sdi, επιλέξτε έναν τυχαίο τριψήφιο. Αιτιολογήστε όπου νομίζετε πως χρειάζεται.\n\n```c\nint mystery(int number) {\n  int i = 0;\n  while(number > 4) {\n    printf(\"Loop %d: %d\\n\", i++, number);\n    number >>= 2;\n  }\n  printf(\"Result: %c\\n\", '0' + number);\n  return number;\n}\n```",
  "hint": "Το `number >>= 2` για θετικό ακέραιο ισοδυναμεί με ακέραια διαίρεση με το 4. Κρατήστε\nέναν πίνακα με τις τιμές των `i` και `number` σε κάθε επανάληψη, προσέχοντας ότι το\n`i++` τυπώνει την τιμή *πριν* την αύξηση. Στο τέλος, σκεφτείτε ποιος χαρακτήρας\nαντιστοιχεί στον κωδικό ASCII `'0' + number` όταν το `number` είναι μεταξύ 0 και 4."
 },
 {
  "id": "exam-2026-jun-q2",
  "kind": "exam",
  "title": "Η συνάρτηση paws",
  "source": {
   "title": "Εξέταση Ιουνίου 2026, Θέμα 2",
   "url": "https://progintro.github.io/exams/2026/progintro-exam-jun-26.pdf",
   "years": [
    2026
   ]
  },
  "chapters": [
   10,
   2
  ],
  "topics": [
   "arrays",
   "strings",
   "undefined-behavior",
   "types"
  ],
  "difficulty": 2,
  "type": "debug",
  "label": "Α10.24",
  "path": "questions/exams/exam-2026-jun-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2026-jun-q2.html",
  "statement": "**Η συνάρτηση paws (15 Μονάδες)**\n\nΖητήσαμε από τον Κλαύδιο να προγραμματίσει κάτι στα γρήγορα και συμπεριέλαβε την\nακόλουθη συνάρτηση `paws` στον κώδικά του:\n\n```c\nvoid paws(char *a, size_t len) {\n    int lo = 0, hi = len;\n    while(lo < hi) {\n      char tmp = a[lo];\n      a[lo++] = a[hi];\n      a[hi--] = tmp;\n    }\n    return;\n}\n```\n\n1. Τι κάνει η συνάρτηση `paws` (μέχρι 15 λέξεις εξήγηση);\n2. Τι θα τυπωθεί στην πρότυπη έξοδο μετά την εκτέλεση της παρακάτω ακολουθίας εντολών;\n\n   ```c\n   char buffer[] = { 33, 0x43, 'B', 0x41, '!', 0 };\n   paws(buffer, 3);\n   printf(\"Result: %s\\n\", buffer);\n   ```\n\n3. Μπορεί να προκύψει κάποιο σφάλμα στην συνάρτηση `paws` όπως είναι γραμμένη; Αν ναι,\n   εξηγήστε γιατί και πως θα το διορθώνατε. Αν όχι, εξηγήστε γιατί αυτή η υλοποίηση είναι\n   ορθή.",
  "hint": "Μετατρέψτε πρώτα τα στοιχεία του `buffer` σε χαρακτήρες με τον πίνακα ASCII (33 και\n0x43, 0x41 σε δεκαδικό). Στη συνέχεια εκτελέστε τον βρόχο με το χέρι, γράφοντας τα\n`lo`, `hi` και τα περιεχόμενα του πίνακα σε κάθε βήμα. Για το σφάλμα, αναρωτηθείτε\nποιος είναι ο δείκτης (index) του τελευταίου έγκυρου στοιχείου ενός πίνακα μήκους\n`len`, τι γίνεται όταν `len` είναι 0, και τι σημαίνει η μετατροπή `size_t` σε `int`."
 },
 {
  "id": "exam-2026-jun-q3",
  "kind": "exam",
  "title": "Επενδύσεις στο Χρηματιστήριο",
  "source": {
   "title": "Εξέταση Ιουνίου 2026, Θέμα 3",
   "url": "https://progintro.github.io/exams/2026/progintro-exam-jun-26.pdf",
   "years": [
    2026
   ]
  },
  "chapters": [
   25,
   15,
   9
  ],
  "topics": [
   "complexity",
   "problem-solving",
   "command-line-args",
   "input-output"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α25.8",
  "path": "questions/exams/exam-2026-jun-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2026-jun-q3.html",
  "statement": "**Επενδύσεις στο Χρηματιστήριο (45 Μονάδες)**\n\nΣε μια στιγμή αυθορμητισμού, αποφασίσαμε να μπούμε ενεργά στον χώρο του χρηματιστηρίου\nκαι των μετοχών. Κάνοντας αυτήν την κίνηση, μάθαμε πως το πρώτο πρόβλημα που πρέπει να\nλύσουμε είναι το πότε πρέπει να πουλήσεις και πότε να αγοράσεις μια μετοχή. Αυτό θα είναι\nκαι το πρόβλημα που θα μας απασχολήσει σε αυτό το θέμα.\n\nΓράψτε ένα πρόγραμμα το οποίο θα διαβάζει από την πρότυπη είσοδο τις τιμές που λαμβάνει\nμια μετοχή σε διαδοχικές μέρες και τυπώνει: (1) την ελάχιστη τιμή της μετοχής και (2) την\nμέγιστη τιμή της μετοχής. Επιπλέον, όταν δοθεί το όρισμα `--optimal` θέλουμε να τυπώνει\nστην πρότυπη έξοδο και τον βέλτιστο συνδυασμό πότε έπρεπε να αγοράσει κανείς την μετοχή,\nπότε να την πουλήσει καθώς και το αναμενόμενο κέρδος (17/45 της βαθμολογίας).\n\nΠεριγράψτε την χρονική και χωρική πολυπλοκότητα του αλγορίθμου σας ως προς τον αριθμό N\nτων ακεραίων και εξηγήστε αν είναι η βέλτιστη (8/45 της βαθμολογίας).\n\nΠαραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ ./stonks\nGive me the number of days: 10\nGive me 10 stock values for each day: 7 1 5 3 6 4 9 2 8 3\nMinimum: 1\nMaximum: 9\n$ ./stonks --optimal\nGive me the number of days: 8\nGive me 8 stock values for each day: 10 9 8 7 1 3 5 6\nMinimum: 1\nMaximum: 10\nOptimal strategy to buy on day 5 and sell on day 8 for profit 5.\n```",
  "hint": "Παρατηρήστε στο δεύτερο παράδειγμα ότι η αγορά πρέπει να γίνει *πριν* την πώληση, άρα\nτο κέρδος δεν είναι απλώς μέγιστο μείον ελάχιστο. Η απλή λύση δοκιμάζει κάθε ζεύγος\nημερών σε O(N²)· σκεφτείτε όμως τι αρκεί να θυμάστε από τις προηγούμενες μέρες όταν\nεξετάζετε την πώληση σε μια συγκεκριμένη μέρα, ώστε να αρκεί ένα πέρασμα. Προσέξτε ότι\nοι μέρες μετρούν από το 1 και ελέγξτε το `argv` με `strcmp`."
 },
 {
  "id": "exam-2026-jun-q4",
  "kind": "exam",
  "title": "World Cup 2026",
  "source": {
   "title": "Εξέταση Ιουνίου 2026, Θέμα 4",
   "url": "https://progintro.github.io/exams/2026/progintro-exam-jun-26.pdf",
   "years": [
    2026
   ]
  },
  "chapters": [
   19,
   18,
   14
  ],
  "topics": [
   "structs",
   "sorting",
   "strings",
   "input-validation",
   "complexity"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α19.12",
  "path": "questions/exams/exam-2026-jun-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2026-jun-q4.html",
  "statement": "**World Cup 2026 (35 Μονάδες)**\n\nΤο παγκόσμιο κύπελλο ποδοσφαίρου μόλις έφτασε! Όλοι και όλες είμαστε έτοιμοι/ες για να\nδούμε τους αγώνες αλλά διαπιστώσαμε πως κάτι λείπει: δεν έχουμε ένα γρήγορο τρόπο να\nυπολογίζουμε την κατάταξη των ομάδων μετά τα αποτελέσματα των αγώνων. Αυτό είναι και το\nπρόβλημα που καλούμαστε να λύσουμε σε αυτό το θέμα.\n\nΓράψτε ένα πρόγραμμα C το οποίο διαβάζει από την πρότυπη είσοδο όλα τα αποτελέσματα\nαγώνων ανάμεσα σε ομάδες και στο τέλος τυπώνει τις ομάδες ταξινομημένες σε φθίνουσα σειρά\nμε βάση την βαθμολογία τους. Σε περίπτωση ισοβαθμίας, χρησιμοποιούμε την διαφορά γκολ για\nνα αποφασίσουμε ποια ομάδα είναι πρώτη (σε περίπτωση ίδιας διαφοράς γκολ, οι ομάδες\nταξινομούνται αλφαβητικά). Μια ομάδα παίρνει 3 βαθμούς σε περίπτωση νίκης, 1 βαθμό σε\nπερίπτωση ισοπαλίας και 0 βαθμούς εάν χάσει. Το αρχείο θα περιέχει έναν αγώνα ανά γραμμή\nκαι η μορφή του θα είναι: `ΟΜΑΔΑ1-ΟΜΑΔΑ2,ΓΚΟΛ1-ΓΚΟΛ2` όπου ΓΚΟΛ1 είναι τα γκολ που\nέβαλε η ΟΜΑΔΑ1 και αντίστοιχα για τα ΓΚΟΛ2/ΟΜΑΔΑ2.\n\nΠοια είναι η χρονική και η χωρική πολυπλοκότητα του αλγορίθμου σας (10/30 της\nβαθμολογίας); Αιτιολογήστε την απάντησή σας και εξηγήστε την σημασία κάθε μεταβλητής που\nθα χρησιμοποιήσετε.\n\nΠαράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ cat games.txt\nGermany-South Korea,4-2\nMexico-New Zealand,3-0\nEcuador-France,1-5\nArgentina-Morocco,3-1\nTurkey-Croatia,2-2\nPortugal-Senegal,2-3\nPortugal-New Zealand,2-0\nEcuador-Croatia,1-2\nFrance-Senegal,1-0\nSouth Korea-Argentina,0-2\nTurkey-Germany,2-2\nMexico-Morocco,3-3\n$ ./scoreboard < games.txt\nFrance, 6, (6 - 1)\nArgentina, 6, (5 - 1)\nMexico, 4, (6 - 3)\nGermany, 4, (6 - 4)\nCroatia, 4, (4 - 3)\nPortugal, 3, (4 - 3)\nSenegal, 3, (3 - 3)\nTurkey, 2, (4 - 4)\nMorocco, 1, (4 - 6)\nSouth Korea, 0, (2 - 6)\nEcuador, 0, (2 - 7)\nNew Zealand, 0, (0 - 5)\n```",
  "hint": "Κρατήστε έναν πίνακα από `struct` (όνομα, βαθμοί, γκολ υπέρ, γκολ κατά) και, για κάθε\nγραμμή, βρείτε ή προσθέστε τις δύο ομάδες. Τα ονόματα περιέχουν κενά (π.χ. \"South\nKorea\"), οπότε διαβάστε ολόκληρη τη γραμμή με `fgets` και χωρίστε την στα `-` και\n`,` αντί για `%s`. Για την ταξινόμηση γράψτε μια συνάρτηση σύγκρισης με τρία\nκριτήρια (βαθμοί, διαφορά γκολ, `strcmp`) για το `qsort`, και σκεφτείτε το κόστος της\nαναζήτησης ομάδας για την πολυπλοκότητα."
 },
 {
  "id": "exam-2026-sep-q1",
  "kind": "exam",
  "title": "Mystery",
  "source": {
   "title": "Εξέταση Σεπτεμβρίου 2026, Θέμα 1",
   "url": "https://progintro.github.io/exams/2026/progintro-exam-sep-26.pdf",
   "years": [
    2026
   ]
  },
  "chapters": [
   6,
   2
  ],
  "topics": [
   "loops",
   "operators",
   "undefined-behavior"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α6.19",
  "path": "questions/exams/exam-2026-sep-q1.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2026-sep-q1.html",
  "statement": "**Mystery [10 Μονάδες]**\n\nΗ συνάρτηση `mystery` δέχεται ως όρισμα έναν ακέραιο αριθμό που αποτελείται από τα 3\nτελευταία ψηφία του sdi σας. Για παράδειγμα, αν ο sdi σας είναι ο sdi2500789 τότε καλούμε\nτην συνάρτηση ως `mystery(789)`. Τι θα τυπώσει η συνάρτηση για τα ψηφία του δικού σας\nsdi; Αιτιολογήστε όπου νομίζετε πως χρειάζεται.\n\n```c\nint mystery(int number) {\n  int i, total = 0;\n  number += 100;\n  printf(\"%s: %d, (%d)\\n\", \"Computing total\", total, i);\n  for(i = 0 ; number ; i++) {\n    total = 10 * total + number % 10;\n    number /= 10;\n    printf(\"%d: total: %d\\n\", i, total);\n  }\n  printf(\"%d: total: %d number: %d\\n\", i, total, number);\n  return total;\n}\n```",
  "hint": "Φτιάξτε έναν πίνακα με τις τιμές των `i`, `number` και `total` σε κάθε επανάληψη,\nξεκινώντας από το `number` *αφού* προστεθεί το 100. Η συνθήκη του `for` είναι απλώς\n`number`: σκεφτείτε πότε γίνεται ψευδής. Προσέξτε την πρώτη `printf`: τι τιμή έχει το\n`i` εκείνη τη στιγμή; Και σκεφτείτε τι γίνεται με τα μηδενικά όταν τα ψηφία μπαίνουν\nστο `total`, π.χ. αν το άθροισμα είναι τετραψήφιο ή τελειώνει σε 0."
 },
 {
  "id": "exam-2026-sep-q2",
  "kind": "exam",
  "title": "Η συνάρτηση cons",
  "source": {
   "title": "Εξέταση Σεπτεμβρίου 2026, Θέμα 2",
   "url": "https://progintro.github.io/exams/2026/progintro-exam-sep-26.pdf",
   "years": [
    2026
   ]
  },
  "chapters": [
   10,
   25
  ],
  "topics": [
   "arrays",
   "loops",
   "undefined-behavior"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α10.19",
  "path": "questions/exams/exam-2026-sep-q2.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2026-sep-q2.html",
  "statement": "**Η συνάρτηση cons (15 Μονάδες)**\n\nΖητήσαμε από την Κλαυδία να προγραμματίσει κάτι στα γρήγορα και χρησιμοποίησε την\nσυνάρτηση `cons` στον κώδικά της:\n\n```c\nint cons(int a[], int n) {\n    int best = 1;\n    int current = 1;\n\n    for (int i = 1; i <= n; i++) {\n        if (a[i] == a[i - 1])\n            current++;\n        else\n            current = 1;\n\n        if (current > best)\n            best = current;\n    }\n\n    return best;\n}\n```\n\nΤι κάνει η συνάρτηση `cons` (μέχρι 15 λέξεις εξήγηση);\n\nΤι θα τυπώσει η παρακάτω ακολουθία εντολών;\n\n```c\n    int arg[] = {4, 4, 2, 6, 7, 7, 7, 3};\n    printf(\"%d\", cons(arg, 6));\n```\n\nΥπάρχει κάποιο σφάλμα στην `cons`, αν `n` είναι το μέγεθος του πίνακα;",
  "hint": "Ιχνηλατήστε τον βρόχο με το `current` και το `best` για κάθε `i` και δείτε ποια\nζευγάρια γειτονικών στοιχείων συγκρίνονται. Στην κλήση, το `n` είναι 6 ενώ ο πίνακας\nέχει 8 στοιχεία: μετρήστε ακριβώς ποια στοιχεία διαβάζει ο βρόχος. Για το σφάλμα,\nρωτήστε ποιος είναι ο μεγαλύτερος έγκυρος δείκτης ενός πίνακα μεγέθους `n` και αν η\nσυνάρτηση δουλεύει για πολύ μικρά `n` (π.χ. 0)."
 },
 {
  "id": "exam-2026-sep-q3",
  "kind": "exam",
  "title": "Το μεγαλύτερο άλμα - polevault",
  "source": {
   "title": "Εξέταση Σεπτεμβρίου 2026, Θέμα 3",
   "url": "https://progintro.github.io/exams/2026/progintro-exam-sep-26.pdf",
   "years": [
    2026
   ]
  },
  "chapters": [
   12,
   9
  ],
  "topics": [
   "command-line-args",
   "floating-point",
   "loops"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α12.22",
  "path": "questions/exams/exam-2026-sep-q3.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2026-sep-q3.html",
  "statement": "**Το μεγαλύτερο άλμα - polevault [25 Μονάδες]**\n\nΜας κάλεσαν από το Diamond League να γράψουμε ένα πρόγραμμα υπολογισμού της\nκαλύτερης επίδοσης σε άλματα επί κοντώ. Το πρόγραμμα θα παίρνει τις επιδόσεις των\nαθλητών/τριών με την σειρά με τις οποίες τις πέτυχαν ως ορίσματα με τον εξής τρόπο: το\nόνομα του/της κάθε αθλητή/τριας θα ακολουθείται από την επίδοση, ενώ στην πρότυπη\nέξοδο περιμένουμε να δούμε το άτομο με την καλύτερη επίδοση. Σε περίπτωση ισοβαθμίας,\nτο άτομο που πέτυχε την υψηλότερη επίδοση πρώτο παίρνει το χρυσό. Παράδειγμα εκτέλεσης\nακολουθεί:\n\n```text\n$ ./polevault Kendricks 5.72 Guttormsen 5.82 Karalis 6.12 Marschall 5.82\nOut of 4 athletes, the gold goes to Karalis with a jump to 6.12!\n```",
  "hint": "Τα ορίσματα έρχονται σε ζεύγη (όνομα, επίδοση) μετά το `argv[0]`, οπότε διατρέξτε το\n`argv` με βήμα 2 και μετατρέψτε την επίδοση σε αριθμό κινητής υποδιαστολής (π.χ. με\n`atof`). Αρκεί να κρατάτε τη θέση του καλύτερου μέχρι στιγμής· η ισοβαθμία λύνεται από\nτο αν η σύγκριση είναι αυστηρή ή όχι. Σκεφτείτε τι γίνεται αν το πλήθος των ορισμάτων\nείναι μονό ή μηδέν, και πώς θα τυπώσετε την επίδοση με δύο δεκαδικά."
 },
 {
  "id": "exam-2026-sep-q4",
  "kind": "exam",
  "title": "Ν-οστό Στοιχείο Λίστας",
  "source": {
   "title": "Εξέταση Σεπτεμβρίου 2026, Θέμα 4",
   "url": "https://progintro.github.io/exams/2026/progintro-exam-sep-26.pdf",
   "years": [
    2026
   ]
  },
  "chapters": [
   21,
   13,
   15
  ],
  "topics": [
   "linked-lists",
   "dynamic-memory",
   "complexity"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α21.10",
  "path": "questions/exams/exam-2026-sep-q4.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2026-sep-q4.html",
  "statement": "**Ν-οστό Στοιχείο Λίστας [25 Μονάδες]**\n\nΓράψτε μια συνάρτηση `nth` η οποία παίρνει ως όρισμα μια λίστα από πίνακες χαρακτήρων\nτύπου `List` μαζί με έναν αριθμό `n` και επιστρέφει μια νέα λίστα με μοναδικό στοιχείο το\nn-οστό στοιχείο της λίστας. Αν δεν υπάρχει n-οστό στοιχείο, το πρόγραμμα θέλουμε να\nτερματίζει με κωδικό εξόδου 1. Για παράδειγμα, αν δοθεί η ακόλουθη λίστα:\n\n```text\n\"foo\" -> \"bar\" -> \"zonk\" -> \"baz\" -> \"hello\" -> NULL\n```\n\nκαι `n=3` περιμένουμε να επιστραφεί η ακόλουθη νέα λίστα (0-indexing όπως στην C):\n\n```text\n\"baz\" -> NULL\n```\n\nΠοια είναι η χρονική και η χωρική πολυπλοκότητα του αλγορίθμου σας (8/25 της\nβαθμολογίας); Ο τύπος `List` δίνεται παρακάτω:\n\n```c\ntypedef struct node {\n  char value[32];\n  struct node * next;\n} * List;\n```",
  "hint": "Προχωρήστε `n` βήματα από την κεφαλή ακολουθώντας τα `next`, ελέγχοντας σε κάθε βήμα\nμήπως τελείωσε η λίστα (και τι γίνεται αν η λίστα είναι κενή ή το `n` αρνητικό). Η\nνέα λίστα είναι ένας καινούργιος κόμβος από `malloc`: αντιγράψτε το `value` (δεν\nανατίθεται ως πίνακας) και βάλτε `next = NULL`, αντί να επιστρέψετε δείκτη μέσα στην\nπαλιά λίστα. Για την πολυπλοκότητα, μετρήστε πόσους κόμβους επισκέπτεστε και πόση\nεπιπλέον μνήμη δεσμεύετε."
 },
 {
  "id": "exam-2026-sep-q5",
  "kind": "exam",
  "title": "Η Μεγαλύτερη Χωρητικότητα - capacity",
  "source": {
   "title": "Εξέταση Σεπτεμβρίου 2026, Θέμα 5",
   "url": "https://progintro.github.io/exams/2026/progintro-exam-sep-26.pdf",
   "years": [
    2026
   ]
  },
  "chapters": [
   25,
   15,
   13
  ],
  "topics": [
   "complexity",
   "arrays",
   "problem-solving"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α25.17",
  "path": "questions/exams/exam-2026-sep-q5.md",
  "url": "https://progintro.github.io/study/questions/exams/exam-2026-sep-q5.html",
  "statement": "**Η Μεγαλύτερη Χωρητικότητα - capacity [25 Μονάδες]**\n\nΟι πολιτικοί μηχανικοί του ΕΜΠ χρειάζονται τη βοήθειά μας! Θέλουν να κατασκευάσουν\nμια σειρά από φράγματα και, προτού ξεκινήσουν τις εργασίες, πρέπει να υπολογίσουν την\n*μέγιστη* δυνατή ποσότητα νερού που μπορεί να αποθηκευτεί ανάμεσα στις διάφορες\nβουνοκορφές. Για λόγους απλοποίησης, θεωρούμε ότι έχουμε $N$ κορυφές τοποθετημένες σε\nίσες αποστάσεις μεταξύ τους. Η κάθε κορυφή $i$ βρίσκεται στη θέση $i$ και έχει ύψος\n$h_i$. Επιλέγοντας δύο κορυφές $i$ και $j$, με $i < j$, σχηματίζεται μαζί με το έδαφος\nμια ορθογώνια δεξαμενή, όπως φαίνεται στο Σχήμα 1 (δεν μας πειράζει αν παρεμβάλλονται\nάλλες βουνοκορφές ενδιάμεσα).\n\nΗ στάθμη του νερού δεν μπορεί φυσικά να ξεπεράσει την χαμηλότερη από τις κορυφές\nπου σχηματίζουν την ορθογώνια δεξαμενή. Για τις ανάγκες του προβλήματος θεωρούμε τη\nχωρητικότητα ως το εμβαδόν του ορθογωνίου που σχηματίζεται από την δεξαμενή.\n\n```text\nύψος\n  8 |    #                   #\n  7 |    #~~~~~~~~~~~~~~~~~~~#~~~~~~~#     ύψος νερού = 7\n  6 |    #~~~#~~~~~~~~~~~~~~~#~~~~~~~#\n  5 |    #~~~#~~~~~~~#~~~~~~~#~~~~~~~#\n  4 |    #~~~#~~~~~~~#~~~#~~~#~~~~~~~#\n  3 |    #~~~#~~~~~~~#~~~#~~~#~~~#~~~#\n  2 |    #~~~#~~~#~~~#~~~#~~~#~~~#~~~#\n  1 |#   #~~~#~~~#~~~#~~~#~~~#~~~#~~~#\n    +--------------------------------- θέση\n     0   1   2   3   4   5   6   7   8\n```\n\n*Σχήμα 1: Παράδειγμα για μια σειρά από κορυφές: $h = [1, 8, 6, 2, 5, 4, 8, 3, 7]$. Οι\nκορυφές στις θέσεις 1 και 8 σχηματίζουν τη δεξαμενή μέγιστης χωρητικότητας. Η απόστασή\nτους είναι $8 - 1 = 7$ και το ύψος του νερού είναι 7, επομένως η χωρητικότητα είναι\n$7 \\cdot 7 = 49$.*\n\n> Σημείωση: στο πρωτότυπο το Σχήμα 1 είναι γράφημα με ράβδους και γραμμοσκιασμένη\n> δεξαμενή· εδώ οι κορυφές σημειώνονται με `#` και το νερό με `~`.\n\nΓράψτε ένα πρόγραμμα το οποίο παίρνει από την πρότυπη είσοδο στην πρώτη γραμμή\nτο πλήθος $N$ των κορυφών και στην δεύτερη γραμμή τα $N$ ακέραια ύψη των κορυφών\n$h_0, h_1, \\ldots, h_{N-1}$ και υπολογίζει τη **μέγιστη δυνατή χωρητικότητα** που μπορεί\nνα σχηματιστεί από μία δεξαμενή καθώς και τις κορυφές ανάμεσα στις οποίες θα εμφανιστεί\nαυτή η χωρητικότητα. Ο αλγόριθμός σας θέλουμε να είναι σωστός αλλά και αποδοτικός.\n\nΠοια είναι η χρονική και η χωρική πολυπλοκότητα της λύσης σας; Αιτιολογήστε σύντομα\nτην απάντησή σας (8/25 της βαθμολογίας).\n\nΠαράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ cat mountains.txt\n9\n1 8 6 2 5 4 8 3 7\n\n$ ./capacity < mountains.txt\nMaximum Capacity between mountains at positions 1 and 8: (8-1) * 7 = 49\n```",
  "hint": "Η χωρητικότητα του ζεύγους $(i, j)$ είναι $(j - i) \\cdot \\min(h_i, h_j)$· ο έλεγχος\nόλων των ζευγών είναι σωστός αλλά $O(N^2)$, οπότε ξεκινήστε από αυτόν και μετά\nψάξτε κάτι γρηγορότερο. Σκεφτείτε δύο δείκτες θέσης, έναν σε κάθε άκρο, που κινούνται\nο ένας προς τον άλλον: ποιον από τους δύο δεν έχει νόημα να κρατήσετε, αφού κάθε\nμετακίνηση μικραίνει το πλάτος; Θυμηθείτε να κρατάτε και τις θέσεις του καλύτερου\nζεύγους, να ελέγχετε την τιμή επιστροφής της `scanf` και να δεσμεύσετε τον πίνακα\nανάλογα με το $N$."
 },
 {
  "id": "hw-2023-hw0-bandit",
  "kind": "homework",
  "title": "Ξεκινώντας με την γραμμή εντολών (bandit)",
  "source": {
   "title": "Εργασία 0 (2023-24), Άσκηση 2",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2023/hw0.pdf",
   "years": [
    2023
   ]
  },
  "chapters": [
   1,
   4
  ],
  "topics": [
   "shell",
   "unix",
   "git"
  ],
  "difficulty": 2,
  "type": "tooling",
  "label": "Α1.11",
  "path": "questions/homework/hw-2023-hw0-bandit.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2023-hw0-bandit.html",
  "statement": "Έχεις χρησιμοποιήσει την γραμμή εντολών; Linux; Γνωρίζεις πως να κάνεις SSH σε\nαπομακρυσμένους servers και να λύνεις προβλήματα με εντολές κονσόλας; Αν όχι, καιρός να\nμάθουμε!\n\nΠροκειμένου να ξεκινήσεις, πήγαινε στην σελίδα:\n[overthewire](https://overthewire.org/wargames/bandit/bandit0.html). Για να\nολοκληρώσεις την άσκηση, θα χρειαστεί να περάσεις όλα τα επίπεδα - μέχρι και το 10ο.\nΣε κάθε επίπεδο, απαιτείται να συνδεθείς μέσω SSH σε έναν διαφορετικό server με\nσυγκεκριμένο port number και στην συνέχεια να λύσεις ένα μικρό πρόβλημα προκειμένου να\nαποκαλυφθεί ο κωδικός (ένα string μορφής `Iequeiw2geecaeHee0losaa3aek`) το οποίο είναι\nο κωδικός SSH για το επόμενο επίπεδο.\n\n**Τεχνικές Προδιαγραφές**\n\n- Repository Name: `progintro/hw0-<YourUsername>`\n- Αρχείο Λύσης Filepath: `command/solution.txt`\n- README Filepath: `command/README.md`\n- **Κάθε γραμμή που θα προστεθεί στο αρχείο `solution.txt` πρέπει να γίνει με\n  διαφορετικό git commit. Κοινώς, θέλουμε να δούμε \\*12\\* διαφορετικά git commits. Η\n  κάθε γραμμή πρέπει να προστεθεί όταν λύσετε το αντίστοιχο πρόβλημα, όχι όλες μαζί\n  στο τέλος.**\n\nΤο περιεχόμενο του `solution.txt` πρέπει να έχει την ακόλουθη μορφή:\n\n```text\n$ cat solution.txt\nbandit0: bandit0\nbandit1: ...\nbandit2: ...\n...\nbandit10: ...\nbandit11: ...\n```\n\nΌπου οι τελείες (...) περιγράφουν το μέρος της λύσης που έχει παραληφθεί. Μια σωστή\nλύση, θα έχει το ακόλουθο [SHA hash](https://en.wikipedia.org/wiki/SHA-2):\n\n```text\n$ sha256sum solution.txt\na95444caa1805c4efa936a720d2761ee0f2f24af8347fbec7e6bd2834607a95c  solution.txt\n```\n\nΗ λύση πρέπει να περιέχει όλους τους κωδικούς μέχρι και τον bandit11. Στο αρχείο\n`README.md` πρέπει να προσθέσετε λεπτομέρειες για τον τρόπο που λύσατε τα επίπεδα. Αν\nεπιθυμείτε να λύσετε και τα επόμενα επίπεδα (φτάνουν μέχρι το 33! αλλά απαιτούν γνώσεις\nαπό μελλοντικά μαθήματα) προφανώς κάτι τέτοιο είναι ευπρόσδεκτο και λεπτομέρειες\nμπορούν να προστεθούν στο αρχείο `README.md`.",
  "hint": "Κάθε επίπεδο του bandit γράφει στη σελίδα του ποιες εντολές θα σας χρειαστούν\n(`ls -a`, `cat`, `file`, `find`, `grep`, `sort`, `uniq`, `strings`, `base64`, `tr`\nκ.ά.)· διαβάστε τα `man` τους. Προσέξτε ονόματα αρχείων που ξεκινούν με `-` ή έχουν\nκενά. Κρατήστε τον κωδικό κάθε επιπέδου μόλις τον βρείτε και κάντε αμέσως commit,\nγιατί ζητούνται 12 ξεχωριστά commits· στο τέλος ελέγξτε το αρχείο με `sha256sum`\n(προσοχή στην ακριβή μορφή κάθε γραμμής και στην αλλαγή γραμμής στο τέλος).\n\n## Δείτε επίσης\n\n- [Υποδειγματική υποβολή φοιτητή](https://progintro.github.io/samples/code/command1/) (περιέχει λύση: δείτε την αφού λύσετε την άσκηση)"
 },
 {
  "id": "hw-2023-hw0-collatz",
  "kind": "homework",
  "title": "Η εικασία Collatz",
  "source": {
   "title": "Εργασία 0 (2023-24), Άσκηση 3",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2023/hw0.pdf",
   "years": [
    2023
   ]
  },
  "chapters": [
   6,
   2,
   4
  ],
  "topics": [
   "loops",
   "integer-representation",
   "command-line-args"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α6.14",
  "path": "questions/homework/hw-2023-hw0-collatz.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2023-hw0-collatz.html",
  "statement": "Η [εικασία Collatz](https://en.wikipedia.org/wiki/Collatz_conjecture) είναι ένα από τα\nπιο διάσημα άλυτα προβλήματα των μαθηματικών. Η εικασία ισχυρίζεται ότι η επανάληψη\nδυο απλών αριθμητικών πράξεων με μια συγκεκριμένη διαδικασία μπορεί να μετατρέψει\nοποιονδήποτε θετικό ακέραιο στο 1. Η διαδικασία των πράξεων έχει ως εξής:\n\n1. Διάλεξε οποιονδήποτε θετικό ακέραιο N.\n2. Αν ο αριθμός είναι 1, τότε τερμάτισε την διαδικασία.\n3. Αν είναι άρτιος, ο επόμενος αριθμός στην ακολουθία θα είναι ο N/2.\n4. Αν είναι περιττός, ο επόμενος αριθμός στην ακολουθία θα είναι ο 3 × N + 1.\n5. Επανάλαβε τα βήματα 2-4 μέχρι να φτάσουμε στο 1.\n\nΓια παράδειγμα, έστω N = 3. Η παραπάνω διαδικασία θα παράξει την ακολουθία: 3, 10, 5,\n16, 8, 4, 2, 1. Για το 42 παίρνουμε την ακολουθία: 42, 21, 64, 32, 16, 8, 4, 2, 1.\n\nΓια κάθε θετικό ακέραιο N, ο αριθμός στοιχείων της ακολουθίας που παράγεται μέχρι να\nκαταλήξουμε στο 1, λέγεται *μήκος ακολουθίας Collatz*. Για παράδειγμα, για N = 3, το\nμήκος της ακολουθίας είναι 8 (η ακολουθία έχει 8 στοιχεία: 3, 10, 5, 16, 8, 4, 2, 1).\nΑντίστοιχα για τον αριθμό 42, το μήκος ακολουθίας Collatz είναι 9. Αν N = 1, τότε έχουμε\nτο ελάχιστο μήκος 1.\n\nΓια το ζητούμενο αυτής της άσκησης, καλείστε να γράψετε ένα πρόγραμμα που βρίσκει το\nμέγιστο μήκος ακολουθίας Collatz σε ένα εύρος αριθμών.\n\n**Τεχνικές Προδιαγραφές**\n\n- Repository Name: `progintro/hw0-<YourUsername>`\n- Αρχείο C (Filepath): `collatz/src/collatz.c`\n- Το αρχείο C που θα υποβληθεί πρέπει να μεταγλωττίζεται χωρίς ειδοποιήσεις για λάθη\n  και με κωδικό επιστροφής (exit code) που να είναι 0. Συγκεκριμένα, το αρχείο σας\n  **πρέπει** να μπορεί να μεταγλωττιστεί επιτυχώς με την ακόλουθη εντολή σε ένα από τα\n  μηχανήματα του εργαστηρίου (linuxXY.di.uoa.gr):\n  `gcc -O0 -m32 -Wall -Wextra -Werror -pedantic -o collatz collatz.c`\n- README Filepath: `collatz/README.md`\n- **Ένα αρχείο που να περιέχει ένα στοιχείο εισόδου και ένα εξόδου \\*διαφορετικά\\* από\n  αυτά της άσκησης. Συγκεκριμένα προτείνουμε να βάλετε έναν συνδυασμό που θεωρείται ότι\n  είναι δύσκολος να γίνει σωστός κατά την υλοποίηση.**\n  - input Filepath: `collatz/test/input`\n  - output Filepath: `collatz/test/output`\n\n  Για παράδειγμα, το περιεχόμενο του input αρχείου μπορεί να είναι: \"100 100000000\" και\n  του αντίστοιχου output: \"950\". Προσοχή: αυτό το παράδειγμα δεν θα γίνει δεκτό από την\n  άσκηση επειδή αυτό το input-output ζευγάρι υπάρχει ήδη παραπάνω, επομένως πρέπει να\n  διαλέξετε κάποιο άλλο.\n- Όλοι οι ακέραιοι που θα δοθούν στο πρόγραμμά σας θα είναι στο εύρος\n  [−100000000, 100000000]\n- Το ελάχιστο κάτω όριο που είναι δεκτό: 1.\n- Το μέγιστο άνω όριο που είναι δεκτό: 100.000.000.\n- Αν δοθεί οποιοσδήποτε μη θετικός αριθμός στα όρια η είσοδος θεωρείται μη αποδεκτή το\n  πρόγραμμα πρέπει να τυπώνει: \"0\".\n- Πρέπει να ολοκληρώνει την εκτέλεση μέσα σε: 4 λεπτά.\n- Μέγιστο μέγεθος αρχείου C που μπορεί να χρησιμοποιηθεί στην υποβολή: 8KB.\n\nΠαρακάτω παραθέτουμε την αλληλεπίδραση με μια ενδεικτική λύση:\n\n```text\nthanassis@linux14:~$ hostname\nlinux14\nthanassis@linux14:~$ gcc -O0 -m32 -Wall -Wextra -Werror -pedantic -o collatz collatz.c\nthanassis@linux14:~$ ./collatz 1 10\n20\nthanassis@linux14:~$ ./collatz 900 1000\n174\nthanassis@linux14:~$ ./collatz 80000 100000\n333\nthanassis@linux14:~$ ./collatz 100 1000000\n525\nthanassis@linux14:~$ ./collatz 100 100000000\n950\nthanassis@linux14:~$ ./collatz -1 100\n0\n```\n\nΕνδεικτικοί χρόνοι:\n\n```text\nthanassis@linux14:~$ time ./collatz 100 1000000\n525\n\nreal 0m1,343s\nuser 0m1,338s\nsys 0m0,004s\nthanassis@linux14:~$ time ./collatz 100 100000000\n950\n\nreal 3m0,212s\nuser 3m0,206s\nsys 0m0,000s\n```\n\nΟ παραπάνω χρόνος μπορεί να είναι και πιο γρήγορος ανάλογα με την υλοποίηση /\nμεταγλώττιση / μηχάνημα στο οποίο τρέχει. Αν επιθυμείτε να τα βελτιώσετε ίσως χρειαστεί\nλίγο παραπάνω έρευνα από μέρους σας σε θέματα για τα οποία δεν έχουμε μιλήσει ακόμα στο\nμάθημα, αλλά φυσικά πιο γρήγορες υποβολές είναι ευπρόσδεκτες:\n\n```text\nthanassis@linux14:~$ time ./collatz_fast 100 100000000\n950\n\nreal 0m8,034s\nuser 0m6,789s\nsys 0m1,244s\n```\n\nΣτο αρχείο `README.md` πρέπει να προσθέσετε οποιεσδήποτε παρατηρήσεις σας κατά την\nδιεκπεραίωση της άσκησης. Ο κώδικας απαιτείται να είναι καλά τεκμηριωμένος με σχόλια\nκαθώς αυτό θα είναι μέρος της βαθμολόγησης. Για την υποβολή με την καλύτερη απόδοση\n(πιο γρήγορη από πλευράς χρόνου) θα ζητήσουμε μια γρήγορη (5λεπτη) παρουσίαση στο\nμάθημα, για την οποία θα λάβει +100% της βαθμολογίας (+50 Μονάδες).",
  "hint": "Γράψτε πρώτα μια συνάρτηση που υπολογίζει το μήκος για ένα N και μετά έναν βρόχο πάνω\nστο εύρος που κρατά το μέγιστο· τα όρια έρχονται από το `argv` με `atoi`. Προσέξτε ότι\nμε `-m32` ο `int` είναι 32 bit, ενώ οι ενδιάμεσοι όροι της ακολουθίας για N κοντά στο\n10^8 ξεπερνούν κατά πολύ το 2^32: χρειάζεστε έναν ευρύτερο ακέραιο τύπο. Σκεφτείτε\nεπίσης τι γίνεται αν το κάτω όριο είναι μεγαλύτερο από το άνω.\n\n## Δείτε επίσης\n\n- [Υποδειγματική υποβολή φοιτητή](https://progintro.github.io/samples/code/collatz1/) (περιέχει λύση: δείτε την αφού λύσετε την άσκηση)"
 },
 {
  "id": "hw-2023-hw1-flawless",
  "kind": "homework",
  "title": "Άψογα Τετράγωνα (Bonus)",
  "source": {
   "title": "Εργασία 1 (2023-24), Άσκηση 3 (Bonus)",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2023/hw1.pdf",
   "years": [
    2023
   ]
  },
  "chapters": [
   11,
   16
  ],
  "topics": [
   "recursion",
   "math-algorithms",
   "integer-representation"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α11.20",
  "path": "questions/homework/hw-2023-hw1-flawless.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2023-hw1-flawless.html",
  "statement": "Αυτή η άσκηση είναι Bonus, δηλαδή η λύση της *δεν* είναι απαραίτητη για να πάρει\nκάποιος/α όλες τις μονάδες της Εργασίας 1. Σε αυτήν την άσκηση θα ασχοληθούμε με μια\nκατηγορία αριθμών που ονομάσαμε *άψογα τετράγωνα*.\n\n**Ορισμός 6.** Ένας φυσικός αριθμός λέγεται *άψογο τετράγωνο* (flawless square), όταν\nείναι τέλειο τετράγωνο και ταυτόχρονα ισούται με το τετράγωνο του αθροίσματος\n*διαδοχικών* ψηφίων του. Τονίζουμε ότι όλα τα ψηφία πρέπει να χρησιμοποιηθούν. Για\nπαράδειγμα, ο αριθμός 1 είναι ένα άψογο τετράγωνο καθώς είναι το τετράγωνο ενός αριθμού\n(1) και ταυτόχρονα το άθροισμα των ψηφίων του στο τετράγωνο (1²) ισούται με τον αρχικό\nαριθμό. Αντίστοιχα, ο αριθμός 81 είναι ένα άψογο τετράγωνο, καθώς είναι τέλειο (9²) και\nταυτόχρονα το άθροισμα των ψηφίων του στο τετράγωνο ισούται με τον αρχικό αριθμό\n((8 + 1)² = 81). Παρακάτω παραθέτουμε μερικά ακόμα παραδείγματα άψογων αριθμών:\n\n```text\n1296    = (1 + 29 + 6)^2                  = 36^2\n3025    = (30 + 25)^2                     = 55^2\n8281    = (8 + 2 + 81)^2 = (82 + 8 + 1)^2 = 91^2\n998001  = (998 + 0 + 0 + 1)^2             = 999^2\n4941729 = (494 + 1729)^2                  = 2223^2\n```\n\nΓια το ζητούμενο αυτής της άσκησης, καλείστε να γράψετε ένα πρόγραμμα το οποίο να\nυπολογίζει το άθροισμα όλων των άψογων τετραγώνων που βρίσκονται σε ένα εύρος φυσικών\nαριθμών.\n\n**Τεχνικές Προδιαγραφές**\n\n- Repository Name: `progintro/hw1-<YourUsername>`\n- C Filepath: `flawless/src/flawless.c`\n- Το πρόγραμμά θα πρέπει να παίρνει δύο ορίσματα από την γραμμή εντολών στην μορφή\n  `./flawless low high`, με το πρώτο (`low`) να είναι το κάτω όριο και το δεύτερο να\n  είναι το άνω όριο (`high`). Τα δύο όρια είναι κλειστά, δηλαδή η αναζήτηση πρέπει να\n  γίνει στο σύνολο `[low, high]`. Για οποιαδήποτε είσοδο δεν είναι μέσα στις\n  προδιαγραφές το πρόγραμμα πρέπει να επιστρέφει με κωδικό εξόδου (exit code) 1. Εάν\n  δοθεί άνω όριο χαμηλότερο του κάτω ορίου το πρόγραμμα πρέπει να τερματίσει με κωδικό\n  εξόδου 1.\n- Όλοι οι ακέραιοι που θα δοθούν στο πρόγραμμά σας θα είναι στο εύρος: [1, 10^12]. Εάν\n  δοθούν μη-θετικοί ακέραιοι ή ακέραιοι άνω του 10^12 το πρόγραμμά σας πρέπει να\n  τερματίζει με κωδικό εξόδου 1. Οποιαδήποτε άλλη μη ακέραια είσοδος είναι εκτός\n  προδιαγραφών και δεν θα ελεγχθεί.\n- Το αρχείο C που θα υποβληθεί πρέπει να μεταγλωττίζεται χωρίς ειδοποιήσεις για λάθη\n  και με κωδικό επιστροφής (exit code) που να είναι 0. Συγκεκριμένα, το αρχείο σας\n  **πρέπει** να μπορεί να μεταγλωττιστεί επιτυχώς με την ακόλουθη εντολή σε ένα από τα\n  μηχανήματα του εργαστηρίου (linuxXY.di.uoa.gr):\n  `gcc -O3 -Wall -Wextra -Werror -pedantic -o flawless flawless.c -lm`\n- Μορφοποίηση: το αρχείο που θα υποβληθεί πρέπει να έχει μορφοποίηση σύμφωνη με το\n  C/C++ στυλ της Google. Για να μορφοποιήσετε το αρχείο σας, μπορείτε να τρέξετε την\n  ακόλουθη εντολή: `clang-format -i -style=Google flawless.c` σε έναν υπολογιστή\n  εργαστηρίου. Μη μορφοποιημένα προγράμματα δεν θα εξεταστούν.\n- README Filepath: `flawless/README.md`\n- **Ένα αρχείο που να περιέχει ένα στοιχείο εισόδου και ένα εξόδου \\*διαφορετικά\\* από\n  αυτά της άσκησης. Συγκεκριμένα προτείνουμε να βάλετε έναν συνδυασμό που θεωρείται ότι\n  είναι δύσκολος να γίνει σωστός κατά την υλοποίηση.**\n  - input Filepath: `flawless/test/input`\n  - output Filepath: `flawless/test/output`\n\n  Για παράδειγμα, το περιεχόμενο του input αρχείου μπορεί να είναι: \"1 100000\" και του\n  αντίστοιχου output: \"184768\". Προσοχή: αυτό το παράδειγμα δεν θα γίνει δεκτό από την\n  άσκηση επειδή αυτό το input-output ζευγάρι υπάρχει ήδη παρακάτω, επομένως πρέπει να\n  διαλέξετε κάποιο άλλο.\n- Πρέπει να ολοκληρώνει την εκτέλεση μέσα σε: 10 δευτερόλεπτα.\n- **Δεν επιτρέπεται να γίνει χρήση πινάκων/δεικτών πέρα από το διάβασμα των ορισμάτων\n  της `main`.**\n- **Δεν επιτρέπεται χρήση προϋπολογισμένων αποτελεσμάτων.** Το πρόγραμμά σας πρέπει να\n  υπολογίζει το αποτέλεσμα χωρίς \"πρότερη γνώση\", δηλαδή χωρίς να έχετε ήδη\n  κωδικοποιήσει τα άψογα τετράγωνα που έχετε βρει από προηγούμενους υπολογισμούς σας\n  μέσα στον κώδικα.\n- Καθώς αυτή η εργασία είναι Bonus, θα ελέγξουμε και ποιοτικά χαρακτηριστικά της\n  υποβολής. Μια ιδιαίτερα δυσνόητη ή μη διαχειρίσιμη λύση (π.χ., 6 nested if-else, 35\n  μεταβλητές στην ίδια συνάρτηση κτλ) θα οδηγήσει σε αφαίρεση μονάδων κατά την κρίση του\n  εξεταστή.\n\nΠαρακάτω παραθέτουμε την αλληλεπίδραση με μια ενδεικτική λύση:\n\n```text\nthanassis@linux14:~$ gcc -O3 -Wall -Wextra -Werror -pedantic -o flawless flawless.c -lm\nthanassis@linux14:~$ ./flawless 1 1000\n182\nthanassis@linux14:~$ ./flawless 1 100000\n184768\nthanassis@linux14:~$ ./flawless 1 10000000\n30940314\nthanassis@linux14:~$ time ./flawless 1 10000000000\n499984803178\n\nreal    0m0,204s\nuser    0m0,203s\nsys     0m0,001s\n```\n\nΣτο αρχείο `README.md` πρέπει να προσθέσετε οποιεσδήποτε παρατηρήσεις σας κατά την\nδιεκπεραίωση της άσκησης. Ο κώδικας απαιτείται να είναι καλά τεκμηριωμένος με σχόλια\nκαθώς αυτό θα είναι μέρος της βαθμολόγησης.",
  "hint": "Διατρέξτε τις ρίζες k (από √low έως √high) αντί για όλους τους αριθμούς του εύρους,\nκαι για κάθε k² ρωτήστε: «μπορώ να κόψω τα ψηφία του σε διαδοχικά κομμάτια με άθροισμα\nk;». Αυτό γράφεται φυσικά αναδρομικά: αφαιρέστε ένα κομμάτι από το τέλος του αριθμού (με\n`%` και `/` σε δύναμη του 10) και ρωτήστε το ίδιο για το υπόλοιπο με μικρότερο στόχο.\nΚόψτε νωρίς τους κλάδους όπου το μερικό άθροισμα ήδη ξεπέρασε το k, και προσέξτε τα\nενδιάμεσα μηδενικά (π.χ. 998001).\n\n## Δείτε επίσης\n\n- [Υποδειγματική υποβολή φοιτητή](https://progintro.github.io/samples/code/flawless1/) (περιέχει λύση: δείτε την αφού λύσετε την άσκηση)"
 },
 {
  "id": "hw-2023-hw1-mirror",
  "kind": "homework",
  "title": "Κατοπτρικά Πρώτα Τετράγωνα",
  "source": {
   "title": "Εργασία 1 (2023-24), Άσκηση 2",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2023/hw1.pdf",
   "years": [
    2023
   ]
  },
  "chapters": [
   15,
   3,
   2
  ],
  "topics": [
   "math-algorithms",
   "complexity",
   "functions",
   "integer-representation"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α15.16",
  "path": "questions/homework/hw-2023-hw1-mirror.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2023-hw1-mirror.html",
  "statement": "Σε αυτήν την άσκηση, καλούμαστε να εντοπίσουμε κάποιους αριθμούς που λέγονται\n*κατοπτρικά πρώτα τετράγωνα* σε ένα εύρος ακεραίων. Πρώτα όμως, πρέπει να βεβαιωθούμε\nότι χρησιμοποιούμε κοινό λεξιλόγιο. Στους ακόλουθους ορισμούς, εξηγούμε τους βασικούς\nόρους.\n\n**Ορισμός 1.** Ένας φυσικός αριθμός λέγεται *τέλειο τετράγωνο*\n([perfect square](https://en.wikipedia.org/wiki/Square_number)), όταν μπορεί να γραφεί\nσαν το τετράγωνο ενός άλλου φυσικού αριθμού. Για παράδειγμα τα 4 (= 2²), 16 (= 4²),\n625 (= 25²) είναι όλα τέλεια τετράγωνα. Αντίθετα οι αριθμοί 7, 8, 624 και ένα σωρό άλλοι\nδεν είναι.\n\n**Ορισμός 2.** Ένας φυσικός αριθμός μεγαλύτερος του 1 ονομάζεται *πρώτος*\n([prime](https://en.wikipedia.org/wiki/Prime_number)) όταν έχει σαν μόνους διαιρέτες (το\nυπόλοιπο της διαίρεσης είναι 0) το 1 και τον εαυτό του. Για παράδειγμα, το 17 είναι\nπρώτος αριθμός, ενώ το 42 δεν είναι, αφού έχει σαν διαιρέτες το 2, το 3 και το 7, εκτός\nαπό τους 1 και 42. Μπορείτε να επιβεβαιώσετε ότι οι πρώτοι αριθμοί που είναι μικρότεροι\nαπό το 100 είναι οι εξής:\n\n```text\n2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97\n```\n\n**Ορισμός 3.** Ένας φυσικός αριθμός λέγεται *παλινδρομικός*\n([palindromic](https://en.wikipedia.org/wiki/Palindromic_number)) όταν διαβάζεται το ίδιο\nείτε ευθέως (από αριστερά προς τα δεξιά) είτε αντιστρόφως. Κάποια παραδείγματα\nπαλινδρομικών αριθμών είναι τα ακόλουθα: 1, 9, 151, 484, 12321, 98766789.\n\n**Ορισμός 4.** Ένα ζευγάρι αριθμών λέγεται *κατοπτρικό* (mirror) εάν τα ψηφία του πρώτου\nδιαβάζοντάς τα από αριστερά προς τα δεξιά ταυτίζονται με τα ψηφία του δεύτερου όταν τα\nδιαβάζουμε από τα δεξιά προς τα αριστερά και αντίστροφα. Για παράδειγμα, τα ακόλουθα\nζεύγη αριθμών είναι κατοπτρικά: 1234 και 4321, 18437 και 73481, 837465 και 564738. Σε\nένα κατοπτρικό ζεύγος αριθμών, λέμε ότι ο ένας είναι *κάτοπτρο* του άλλου.\n\n**Ορισμός 5.** Ένας φυσικός αριθμός είναι ένα *κατοπτρικό πρώτο τετράγωνο* όταν:\n\n1. Είναι τέλειο τετράγωνο ενός πρώτου αριθμού.\n2. Το κάτοπτρό του είναι επίσης τέλειο τετράγωνο ενός πρώτου αριθμού.\n3. Δεν είναι παλινδρομικός.\n\nΓια παράδειγμα, ο αριθμός 12769 είναι ένα κατοπτρικό πρώτο τετράγωνο, καθώς: (α) είναι\nτο τετράγωνο ενός πρώτου αριθμού (113² = 12769), (β) το κάτοπτρό του 96721 είναι επίσης\nτο τετράγωνο ενός πρώτου αριθμού (311² = 96721) και (γ) δεν είναι παλινδρομικός.\n\nΓια το ζητούμενο αυτής της άσκησης, καλείστε να γράψετε ένα πρόγραμμα το οποίο να\nυπολογίζει το άθροισμα όλων των κατοπτρικών πρώτων τετραγώνων που βρίσκονται σε ένα\nεύρος φυσικών αριθμών.\n\n**Τεχνικές Προδιαγραφές**\n\n- Repository Name: `progintro/hw1-<YourUsername>`\n- C Filepath: `mirror/src/mirror.c`\n- Το πρόγραμμά θα πρέπει να παίρνει δύο ορίσματα από την γραμμή εντολών στην μορφή\n  `./mirror low high`, με το πρώτο (`low`) να είναι το κάτω όριο και το δεύτερο να είναι\n  το άνω όριο (`high`). Τα δύο όρια είναι κλειστά, δηλαδή η αναζήτηση πρέπει να γίνει\n  στο σύνολο `[low, high]`. Για οποιαδήποτε είσοδο δεν είναι μέσα στις προδιαγραφές το\n  πρόγραμμα πρέπει να επιστρέφει με κωδικό εξόδου (exit code) 1. Εάν δοθεί άνω όριο\n  χαμηλότερο του κάτω ορίου το πρόγραμμα πρέπει να τερματίσει με κωδικό εξόδου 1.\n- Όλοι οι φυσικοί που θα δοθούν στο πρόγραμμά σας θα είναι στο εύρος: [1, 10^15]. Εάν\n  δοθούν μη-θετικοί ακέραιοι ή ακέραιοι άνω του 10^15 το πρόγραμμά σας πρέπει να\n  τερματίζει με κωδικό εξόδου 1. Οποιαδήποτε άλλη μη ακέραια είσοδος -- για παράδειγμα\n  το string \"mpampis\" -- είναι εκτός προδιαγραφών και δεν θα ελεγχθεί.\n- Το αρχείο C που θα υποβληθεί πρέπει να μεταγλωττίζεται χωρίς ειδοποιήσεις για λάθη\n  και με κωδικό επιστροφής (exit code) που να είναι 0. Συγκεκριμένα, το αρχείο σας\n  **πρέπει** να μπορεί να μεταγλωττιστεί επιτυχώς με την ακόλουθη εντολή σε ένα από τα\n  μηχανήματα του εργαστηρίου (linuxXY.di.uoa.gr):\n  `gcc -O3 -Wall -Wextra -Werror -pedantic -o mirror mirror.c -lm`\n- README Filepath: `mirror/README.md`\n- **Ένα αρχείο που να περιέχει ένα στοιχείο εισόδου και ένα εξόδου \\*διαφορετικά\\* από\n  αυτά της άσκησης. Συγκεκριμένα προτείνουμε να βάλετε έναν συνδυασμό που θεωρείται ότι\n  είναι δύσκολος να γίνει σωστός κατά την υλοποίηση.**\n  - input Filepath: `mirror/test/input`\n  - output Filepath: `mirror/test/output`\n\n  Για παράδειγμα, το περιεχόμενο του input αρχείου μπορεί να είναι: \"1 100000\" και του\n  αντίστοιχου output: \"110620\". Προσοχή: αυτό το παράδειγμα δεν θα γίνει δεκτό από την\n  άσκηση επειδή αυτό το input-output ζευγάρι υπάρχει ήδη παρακάτω, επομένως πρέπει να\n  διαλέξετε κάποιο άλλο.\n- Πρέπει να ολοκληρώνει την εκτέλεση μέσα σε: 60 δευτερόλεπτα.\n- **Δεν επιτρέπεται να γίνει χρήση πινάκων/δεικτών πέρα από το διάβασμα των ορισμάτων\n  της `main`.**\n- **Δεν επιτρέπεται χρήση προϋπολογισμένων αποτελεσμάτων.** Το πρόγραμμά σας πρέπει να\n  υπολογίζει το αποτέλεσμα χωρίς \"πρότερη γνώση\", δηλαδή χωρίς να έχετε ήδη\n  κωδικοποιήσει τα κατοπτρικά πρώτα τετράγωνα που έχετε βρει από προηγούμενους\n  υπολογισμούς σας μέσα στον κώδικα.\n\nΠαρακάτω παραθέτουμε την αλληλεπίδραση με μια ενδεικτική λύση:\n\n```text\nthanassis@linux14:~$ gcc -O3 -Wall -Wextra -Werror -pedantic -o mirror mirror.c -lm\nthanassis@linux14:~$ ./mirror 1 100000\n110620\nthanassis@linux14:~$ ./mirror 1 10000000\n15633754\nthanassis@linux14:~$ ./mirror 1 1000000000000\n53009475688\nthanassis@linux14:~$ time ./mirror 1 1000000000000\n53009475688\n\nreal    0m0,025s\nuser    0m0,023s\nsys     0m0,000s\n```\n\nΚατά την διάρκεια της αποσφαλμάτωσης του προγράμματος, μπορούμε να επιβεβαιώσουμε τα\nεπιμέρους αποτελέσματα τυπώνοντας τους αριθμούς που αποτελούν κάθε άθροισμα. Για\nπαράδειγμα, το πρώτο αποτέλεσμα είναι 110620 = 169 + 961 + 12769 + 96721 - και αυτοί οι\n4 αριθμοί είναι τα μόνα κατοπτρικά πρώτα τετράγωνα στο εύρος [1, 100000].\n\nΣτο αρχείο `README.md` πρέπει να προσθέσετε οποιεσδήποτε παρατηρήσεις σας κατά την\nδιεκπεραίωση της άσκησης. Ο κώδικας απαιτείται να είναι καλά τεκμηριωμένος με σχόλια\nκαθώς αυτό θα είναι μέρος της βαθμολόγησης.",
  "hint": "Μην διατρέχετε όλους τους αριθμούς του εύρους (μέχρι 10^15): διατρέξτε τους υποψήφιους\nπρώτους p με p² στο εύρος, δηλαδή μέχρι την τετραγωνική ρίζα του `high`. Χρειάζεστε\nμικρές συναρτήσεις για «είναι πρώτος», «κάτοπτρο αριθμού» (με `%` και `/`) και «είναι\nτέλειο τετράγωνο» (προσοχή στη στρογγυλοποίηση της `sqrt` σε μεγάλους αριθμούς). Οι\nτιμές και το άθροισμα δεν χωράνε σε `int`, και θυμηθείτε ότι δεν επιτρέπονται πίνακες.\n\n## Δείτε επίσης\n\n- [Υποδειγματική υποβολή φοιτητή](https://progintro.github.io/samples/code/mirror1/) (περιέχει λύση: δείτε την αφού λύσετε την άσκηση)"
 },
 {
  "id": "hw-2023-hw1-newton",
  "kind": "homework",
  "title": "Η Μέθοδος Newton-Raphson",
  "source": {
   "title": "Εργασία 1 (2023-24), Άσκηση 1",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2023/hw1.pdf",
   "years": [
    2023
   ]
  },
  "chapters": [
   8,
   3,
   4
  ],
  "topics": [
   "floating-point",
   "loops",
   "functions",
   "command-line-args",
   "math-algorithms"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α8.7",
  "path": "questions/homework/hw-2023-hw1-newton.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2023-hw1-newton.html",
  "statement": "Για πολυώνυμα 5ου βαθμού και πάνω δεν υπάρχει κλειστή μορφή υπολογισμού των ριζών\n([Abel-Ruffini](https://en.wikipedia.org/wiki/Abel%E2%80%93Ruffini_theorem)), οπότε\nκαταφεύγουμε στις προσεγγιστικές μεθόδους της αριθμητικής ανάλυσης.\n\nΗ μέθοδος Newton-Raphson, γνωστή και πιο απλά ως\n[μέθοδος Newton](https://en.wikipedia.org/wiki/Newton%27s_method), μας επιτρέπει να\nβρίσκουμε προσεγγιστικές λύσεις σε πραγματικές συναρτήσεις. Η μέθοδος Newton ορίζεται\nως εξής: Δεδομένης μιας πραγματικής συνάρτησης $f(x)$ και της παραγώγου της $f'(x)$,\nξεκινώντας με ένα τυχαίο $x_0$ μία καλύτερη προσέγγιση μιας ρίζας του πολυωνύμου $x_1$\nδίνεται από την σχέση:\n\n$$x_1 = x_0 - \\frac{f(x_0)}{f'(x_0)}$$\n\nΑντίστοιχα, η γενική αναδρομική σχέση της μεθόδου του Νεύτωνα είναι:\n\n$$x_{n+1} = x_n - \\frac{f(x_n)}{f'(x_n)}$$\n\nόπου $x_{n+1}$ είναι η προσεγγιστική τιμή μιας ρίζας της συνάρτησης $f(x)$ μετά από\n$n + 1$ επαναλήψεις. Το Σχήμα 1 της εκφώνησης δείχνει πως η μέθοδος ξεκινάει από ένα\nσημείο της καμπύλης $x_n$ και χρησιμοποιεί την κλίση της καμπύλης (την εφαπτομένη στο\n$(x_n, f(x_n))$) προκειμένου στην επόμενη επανάληψη το $x_{n+1}$ (το σημείο όπου η\nεφαπτομένη τέμνει τον άξονα x) να είναι μια καλύτερη προσέγγιση μιας ρίζας του\nπολυωνύμου. Ισχύει αυτό πάντα; Μπορείτε να βρείτε κάποια περίπτωση που η $x_{n+1}$\nπροσέγγιση είναι χειρότερη της αρχικής $x_n$;\n\nΓια το ζητούμενο αυτής της άσκησης, καλείστε να γράψετε ένα πρόγραμμα που υπολογίζει\nαυτόματα τις ρίζες (τα x για τα οποία μηδενίζεται) *οποιουδήποτε* πολυωνύμου 5ου βαθμού\nμέσα σε δευτερόλεπτα.\n\n**Τεχνικές Προδιαγραφές**\n\n- Repository Name: `progintro/hw1-<YourUsername>`\n- C Filepath: `newton/src/newton.c`\n- Το πρόγραμμά θα πρέπει να παίρνει επτά ορίσματα από την γραμμή εντολών στην μορφή\n  `./newton a0 a1 a2 a3 a4 a5 x0`. Για την σημασιολογία των ορισμάτων, δείτε παρακάτω\n  την χρήση του προγράμματος. Για οποιαδήποτε είσοδο δεν είναι μέσα στις προδιαγραφές\n  το πρόγραμμα πρέπει να επιστρέφει με κωδικό εξόδου (exit code) 1.\n- Για ένα πολυώνυμο 5ου βαθμού $a_0 + a_1x + a_2x^2 + a_3x^3 + a_4x^4 + a_5x^5$ και μια\n  αρχική ρίζα $x_0$ το πρόγραμμα θα εκτελεστεί ως εξής:\n  `$ ./newton a_0 a_1 a_2 a_3 a_4 a_5 x_0`\n- Όλες οι παράμετροι θα είναι σε δεκαδική μορφή τύπου `double`. Συνιστούμε να\n  χρησιμοποιήσετε την συνάρτηση βιβλιοθήκης `strtod` για να κάνετε την μετατροπή από\n  όρισμα σε double. Δεν χρειάζεται να ελέγξετε για συνθήκες σφάλματος κατά την μετατροπή\n  σε `double` - εγγυώμαστε ότι όλα τα δεδομένα εισόδου θα είναι αριθμοί και ότι οι\n  αριθμοί αυτοί θα είναι επαρκώς μικροί για να χωράνε σε double.\n- Το αρχείο C που θα υποβληθεί πρέπει να μεταγλωττίζεται χωρίς ειδοποιήσεις για λάθη\n  και με κωδικό επιστροφής (exit code) που να είναι 0. Συγκεκριμένα, το αρχείο σας\n  **πρέπει** να μπορεί να μεταγλωττιστεί επιτυχώς με την ακόλουθη εντολή σε ένα από τα\n  μηχανήματα του εργαστηρίου (linuxXY.di.uoa.gr):\n  `gcc -O3 -Wall -Wextra -Werror -pedantic -o newton newton.c -lm`\n- README Filepath: `newton/README.md`\n- **Ένα αρχείο που να περιέχει στοιχεία εισόδου και ένα εξόδου διαφορετικά από αυτά\n  της άσκησης. Συγκεκριμένα προτείνουμε να βάλετε έναν συνδυασμό που θεωρείται ότι\n  είναι δύσκολος να γίνει σωστός.**\n  - input Filepath: `newton/test/input`\n  - output Filepath: `newton/test/output`\n\n  Παράδειγμα που όμως δεν θα γίνει δεκτό από την άσκηση επειδή είναι ήδη στα\n  παραδείγματα παρακάτω, για το input: `1.0 0.0 1.0 0.0 0.0 0.0 2.0` και για το output:\n  `incomplete`.\n- Όλα τα αποτελέσματα θα πρέπει να είναι δεκαδικοί με δύο ψηφία ακριβείας και πρόσημο.\n- Συνθήκες τερματισμού: ο αλγόριθμος πρέπει να τερματίσει *όταν*:\n  1. Ο αλγόριθμος έχει συγκλίνει και ισχύει: $|x_{n+1} - x_n| < 10^{-6}$. Σε αυτήν την\n     περίπτωση τυπώνουμε το αποτέλεσμα $x_{n+1}$ με ακρίβεια δύο δεκαδικών ψηφίων και\n     πρόσημο.\n  2. Ο αλγόριθμος αποκλίνει (π.χ., διαίρεση με 0). Σε αυτήν την περίπτωση τυπώνουμε το\n     αποτέλεσμα `nan`.\n  3. Ο αλγόριθμος δεν τερματίζει μετά από 1000 επαναλήψεις. Σε αυτήν την περίπτωση\n     τυπώνουμε το αποτέλεσμα `incomplete`.\n- Πρέπει να ολοκληρώνει την εκτέλεση μέσα σε: 10 δευτερόλεπτα.\n\nΠαρακάτω παραθέτουμε την αλληλεπίδραση με μια ενδεικτική λύση:\n\n```text\nthanassis@linux14:~$ hostname\nlinux14\nthanassis@linux14:~$ gcc -O3 -Wall -Wextra -Werror -pedantic -o newton newton.c -lm\nthanassis@linux14:~$ ./newton 1.0 2.0 3.0 4.0 5.0 6.0 1.0\n-0.67\nthanassis@linux14:~$ ./newton 1.0 0.0 1.0 0.0 0.0 0.0 2.0\nincomplete\nthanassis@linux14:~$ ./newton 1.0 0.0 1.0 0.0 0.0 0.0 0.0\nnan\n```\n\nΜπορούμε να επιβεβαιώσουμε τα αποτελέσματα των υπολογισμών μας αποτιμώντας το\nπολυώνυμο. Για παράδειγμα, το $a_0 + a_1x + a_2x^2 + a_3x^3 + a_4x^4 + a_5x^5$ για\n$x = -0.67$ κάνει 0.00112899 (σχεδόν 0 - μπορούμε να πάρουμε ρίζες που προσεγγίζουν το\nμηδέν καλύτερα αυξάνοντας την ακρίβεια). Δοκιμάστε και εσείς με τα δικά σας πολυώνυμα\nγια να δείτε αν όντως το πρόγραμμά σας τα καταφέρνει!\n\nΣτο αρχείο `README.md` πρέπει να προσθέσετε οποιεσδήποτε παρατηρήσεις σας κατά την\nδιεκπεραίωση της άσκησης. Ο κώδικας απαιτείται να είναι καλά τεκμηριωμένος με σχόλια\nκαθώς αυτό θα είναι μέρος της βαθμολόγησης.",
  "hint": "Γράψτε δύο μικρές συναρτήσεις, μία για την τιμή του πολυωνύμου και μία για την\nπαράγωγό του (υπολογίστε τους συντελεστές της παραγώγου με το χέρι), και έναν βρόχο που\nσταματά με τρεις διαφορετικούς τρόπους: σύγκλιση, μηδενική παράγωγος, όριο\nεπαναλήψεων. Ελέγξτε ότι το `argc` είναι ακριβώς 8. Για την έξοδο αρκεί η κατάλληλη\nμορφή του `printf` με υποχρεωτικό πρόσημο και δύο δεκαδικά· σκεφτείτε και τι θα τυπώσει\nένα αποτέλεσμα όπως −0.001.\n\n## Δείτε επίσης\n\n- [Υποδειγματική υποβολή φοιτητή](https://progintro.github.io/samples/code/newton1/) (περιέχει λύση: δείτε την αφού λύσετε την άσκηση)"
 },
 {
  "id": "hw-2023-hw2-coop",
  "kind": "homework",
  "title": "Συνεργασία (Prisoner's Dilemma)",
  "source": {
   "title": "Εργασία 2 (2023-24), Άσκηση 3",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2023/hw2.pdf",
   "years": [
    2023
   ]
  },
  "chapters": [
   9,
   8
  ],
  "topics": [
   "input-output",
   "loops",
   "problem-solving"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α9.15",
  "path": "questions/homework/hw-2023-hw2-coop.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2023-hw2-coop.html",
  "statement": "Πολλά επιτραπέζια παιχνίδια (π.χ. το [Uno](https://en.wikipedia.org/wiki/Uno_(card_game)))\nέχουν πολλούς γύρους όπου σε κάθε γύρο μπορείς να συνεργαστείς με τον διπλανό σου ή να\nτον τιμωρήσεις, και η επιλογή σου επηρεάζει το πώς θα συμπεριφερθούν οι άλλοι στη\nσυνέχεια. Τέτοιες ερωτήσεις μελετά η θεωρία παιγνίων\n([game theory](https://en.wikipedia.org/wiki/Game_theory)).\n\nΈνας τρόπος να μοντελοποιήσουμε τέτοια παιχνίδια με πολλούς γύρους όπου οι παίκτες\nσυνεργάζονται ή όχι είναι το\n[Prisoner's Dilemma](https://en.wikipedia.org/wiki/Prisoner%27s_dilemma). Σε κάθε γύρο\nαυτού του παιχνιδιού, δύο παίκτες Α και Β αποφασίζουν αν θα συνεργαστούν (cooperate) ή\nόχι (defect). Αν και οι δύο συνεργαστούν τότε αποκομίζουν κάποιους πόντους (έστω Reward\n(R) = 3). Αν και οι δύο δεν συνεργαστούν τότε παίρνουν λιγότερους πόντους (έστω Payoff\n(P) = 1). Αν ο ένας (έστω ο Α) αποφασίσει να συνεργαστεί και ο Β τον \"προδώσει\" χωρίς να\nσυνεργαστεί τότε ο Β θα αποκομίσει περισσότερους πόντους (έστω Temptation (T) = 5) ενώ ο\nΑ δεν θα πάρει καθόλου πόντους (έστω Sucker (S) = 0). Ένας τρόπος να συνοψίσουμε το\nπαραπάνω παιχνίδι πόντων είναι με έναν πίνακα (payoff matrix):\n\n| A / B | B συνεργάζεται | B δεν συνεργάζεται |\n| --- | --- | --- |\n| A συνεργάζεται | A: 3, B: 3 | A: 0, B: 5 |\n| A δεν συνεργάζεται | A: 5, B: 0 | A: 1, B: 1 |\n\nΌμως τα περισσότερα παιχνίδια δεν τελειώνουν στον πρώτο γύρο! Για παράδειγμα, αν στον\nπρώτο γύρο είδε ο Α ότι ο Β δεν συνεργάστηκε, ο Α μπορεί να αποφασίσει ότι δεν θα\nσυνεργαστεί στον δεύτερο γύρο και θα περιμένει να δει πως θα \"συμπεριφερθεί\" ο Β στον\nδεύτερο γύρο. Αντίστοιχες αποφάσεις μπορεί να έχει στο μυαλό του και ο Β.\n\nΓια το ζητούμενο αυτής της άσκησης, ο στόχος είναι να γράψετε ένα πρόγραμμα που θα\nαποφασίζει πως να συμπεριφερθεί αποδοτικά σε τέτοια επαναληπτικά παιχνίδια αποφάσεων.\n\n**Τεχνικές Προδιαγραφές**\n\n- Repository Name: `progintro/hw2-<YourUsername>`\n- C Filepath: `coop/src/coop.c`\n- Το πρόγραμμα θα πρέπει να δέχεται από την πρότυπη είσοδο (stdin) 2 χαρακτήρες: 'C'\n  (Cooperate), 'D' (Defect / Don't cooperate) - όλοι οι άλλοι χαρακτήρες αγνοούνται. Το\n  πρόγραμμα θα πρέπει να τερματίζει με exit code 0 όταν λάβει EOF.\n- Όταν ξεκινήσει το πρόγραμμά μας πρέπει να τυπώσει την εντολή που επιθυμεί **πριν**\n  επιχειρήσει να διαβάσει την εντολή του άλλου παίκτη. Η εντολή του άλλου παίκτη\n  παρέχεται μόνο αφού το πρόγραμμά σας τυπώσει την δική του εντολή.\n- Το πρόγραμμα θα πρέπει να τυπώνει εντολές ως χαρακτήρες σε δύο μορφές: 'C'\n  (Cooperate) και 'D' (Defect / Don't Cooperate). Μετά από κάθε εντολή το πρόγραμμά σας\n  **πρέπει** να τυπώνει καινούρια γραμμή ('\\n').\n- Για την είσοδο και έξοδο του προγράμματος μπορούν να χρησιμοποιηθούν **μόνο** οι\n  συναρτήσεις `getchar` και `putchar`.\n- Το πρόγραμμά σας **πρέπει** να τυπώνει σε κάθε γύρο την απόφασή του ανεξαρτήτως του\n  buffering που μπορεί να υπάρχει - συνίσταται η χρήση της συνάρτησης `fflush` μετά από\n  κάθε κλήση της `putchar`.\n- Το αρχείο C που θα υποβληθεί πρέπει να μεταγλωττίζεται χωρίς ειδοποιήσεις για λάθη\n  και με κωδικό επιστροφής (exit code) που να είναι 0. Συγκεκριμένα, το αρχείο σας\n  **πρέπει** να μπορεί να μεταγλωττιστεί επιτυχώς με την ακόλουθη εντολή σε ένα από τα\n  μηχανήματα του εργαστηρίου (linuxXY.di.uoa.gr):\n  `gcc -Os -Wall -Wextra -Werror -pedantic -o coop coop.c -lm`\n- Το πρόγραμμά μας πρέπει να παίρνει τουλάχιστον 1 πόντο σε κάθε 1000 γύρους με έναν\n  εκδικητικό παίκτη.\n- Το πρόγραμμά μας πρέπει να παίρνει τουλάχιστον 3000 πόντους σε κάθε 1000 γύρους με\n  έναν συνεργατικό παίκτη.\n- Το πρόγραμμά μας πρέπει να παίζει τουλάχιστον μία φορά D και μία φορά C σε κάθε 1000\n  γύρους παιχνιδιού.\n- README Filepath: `coop/README.md`\n- Μέγιστος αριθμός γύρων: 10^6.\n- Πρέπει να ολοκληρώνει την εκτέλεση 1000 εντολών μέσα σε: 1 δευτερόλεπτο.\n\nΑς προσπαθήσουμε να παίξουμε με μια ενδεικτική λύση (όχι η καλύτερη):\n\n```text\n$ gcc -Os -Wall -Wextra -Werror -pedantic -o coop coop.c -lm\n$ ./coop\nC\n```\n\nΠαρατηρούμε ότι το πρόγραμμα έπαιξε \"C\" (Cooperate). Σε απάντηση μπορούμε να απαντήσουμε\nD και μετά Enter:\n\n```text\n$ gcc -Os -Wall -Wextra -Werror -pedantic -o coop coop.c -lm\n$ ./coop\nC\nD\nD\n```\n\nΠαρατηρούμε ότι αφού γράψαμε \"D\" (Defect) το πρόγραμμα μας απάντησε με \"D\" για τον\nεπόμενο γύρο. Έστω ότι απαντάμε D σε αυτόν τον γύρο και εμείς. Σύνολο σε αυτούς τους δύο\nγύρους επομένως εμείς (που γράφουμε από το stdin) συλλέξαμε 5 + 1 = 6 πόντους ενώ η\nενδεικτική μας λύση (coop) μάζεψε 0 + 1 = 1 πόντους.\n\nΈστω ότι θέλουμε να δούμε πως συμπεριφέρεται μια ενδεικτική (όχι η καλύτερη) λύση όταν\nπαίζει με έναν \"εκδικητικό\" παίκτη που πάντα δεν συνεργάζεται:\n\n```text\n$ echo > input; for i in `seq 1 1000`; do echo D >> input; done\n$ ./coop < input | head -n -1 > output\n$ grep -c D output\n42\n$ grep -c C output\n958\n```\n\nΕπομένως παρατηρούμε ότι το πρόγραμμά μας συνεργάστηκε 958 φορές και 42 δεν\nσυνεργάστηκε, επομένως συγκέντρωσε 958 · 0 + 42 = 42 πόντους. Αντίστοιχα μπορούμε να\nελέγξουμε πως συμπεριφέρεται με έναν \"συνεργατικό\" παίκτη:\n\n```text\n$ echo > input; for i in `seq 1 1000`; do echo C >> input; done\n$ ./coop < input | head -n -1 > output\n$ grep -c D output\n3\n$ grep -c C output\n997\n```\n\nΕπομένως παρατηρούμε ότι το πρόγραμμά μας συνεργάστηκε 997 φορές και 3 δεν\nσυνεργάστηκε, επομένως συγκέντρωσε 997 · 3 + 3 · 5 = 3006 πόντους. Αν θέλετε να\nδοκιμάσετε διαφορετικές στρατηγικές και να δείτε πως θα \"έπαιζε\" με διαφορετικούς\nπαίκτες παραθέτουμε ένα ενδεικτικό (όχι το τελικό!) script \"διαιτητή\" στο ακόλουθο URL:\n<https://github.com/progintro/data/blob/main/scripts/referee.py> που μπορεί να τρέξει\nδιαφορετικές εκδοχές του προγράμματός σας για έναν αριθμό γύρων και να σας δώσει το\nscore του πρώτου παίκτη. Για παράδειγμα:\n\n```text\n# Download referee\n$ curl -O https://raw.githubusercontent.com/progintro/data/main/scripts/referee.py\n# Check what's my score against the `coop` implementation\n$ python3 referee.py ./smart_coop ./coop 1000\n3016\n```\n\nΣτο αρχείο `README.md` πρέπει να προσθέσετε οποιεσδήποτε παρατηρήσεις σας κατά την\nδιεκπεραίωση της άσκησης. Ο κώδικας απαιτείται να είναι καλά τεκμηριωμένος με σχόλια\nκαθώς αυτό θα είναι μέρος της βαθμολόγησης. Για τις υποβολές με την καλύτερη απόδοση\n(αυτές που θα συγκεντρώσουν τους περισσότερους βαθμούς σε παιχνίδια με όλες τις άλλες\nυποβολές) θα υπάρχει bonus βαθμολογία: η πρώτη υποβολή θα λάβει +100%, η δεύτερη +70%\nκαι η τρίτη +40%.",
  "hint": "Η δομή είναι ένας βρόχος «τύπωσε κίνηση, `fflush`, διάβασε την κίνηση του αντιπάλου με\n`getchar` αγνοώντας ό,τι δεν είναι 'C' ή 'D', μέχρι το `EOF`». Η στρατηγική μπορεί να\nκρατά λίγες μεταβλητές κατάστασης (π.χ. την τελευταία κίνηση του αντιπάλου ή μετρητές).\nΕλέγξτε ότι η στρατηγική σας ικανοποιεί και τους τρεις ελάχιστους όρους (εκδικητικός,\nσυνεργατικός παίκτης, τουλάχιστον ένα C και ένα D ανά 1000 γύρους), και διαβάστε για\nκλασικές στρατηγικές όπως το tit-for-tat.\n\n## Δείτε επίσης\n\n- [Υποδειγματική υποβολή φοιτητή](https://progintro.github.io/samples/code/coop1/) (περιέχει λύση: δείτε την αφού λύσετε την άσκηση)"
 },
 {
  "id": "hw-2023-hw2-dna",
  "kind": "homework",
  "title": "DNA Matching",
  "source": {
   "title": "Εργασία 2 (2023-24), Άσκηση 2",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2023/hw2.pdf",
   "years": [
    2023
   ]
  },
  "chapters": [
   25,
   18,
   14
  ],
  "topics": [
   "dynamic-programming",
   "strings",
   "files",
   "dynamic-memory"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α25.2",
  "path": "questions/homework/hw-2023-hw2-dna.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2023-hw2-dna.html",
  "statement": "Ένα εργαστήριο βιοπληροφορικής ψάχνει λύσεις για να βρίσκει *αποδοτικά* κοινές\nαλληλουχίες DNA ανάμεσα σε διαφορετικά άτομα ή ακόμα και οργανισμούς, γνωστό και ως\n[DNA matching](https://www.ancestry.com/cs/dna-help/matches/dna-matching).\n\nΤο [DNA](https://en.wikipedia.org/wiki/DNA) συνήθως το αναπαριστούμε με την μορφή μιας\nαλυσίδας (συμβολοσειράς) από τέσσερα διαφορετικά στοιχεία που λέγονται *βάσεις*: A\n(Αδενίνη), G (Γουανίνη), T (Θυμίνη) και C (Κυτοσίνη) τα οποία μπορούν να συνδυαστούν με\nοποιαδήποτε σειρά. Προκειμένου να κάνουμε DNA matching θέλουμε να δούμε αν υπάρχουν\nκοινά τμήματα σε αυτές τις αλυσίδες DNA και να δούμε πόσο μεγάλες είναι. Το Σχήμα 4 της\nεκφώνησης δείχνει ένα παράδειγμα δύο αλυσίδων με κοινό τμήμα: οι αλυσίδες\n`CATTAGATATAGACG` και `CTATAGATATAGGGC` έχουν κοινό το τμήμα `TAGATATAG`.\n\nΓια το ζητούμενο αυτής της άσκησης, καλείστε να γράψετε ένα πρόγραμμα που διαβάζει δύο\nαλυσίδες DNA, βρίσκει την μέγιστη κοινή αλυσίδα ανάμεσα στις δύο και την τυπώνει.\n\n**Τεχνικές Προδιαγραφές**\n\n- Repository Name: `progintro/hw2-<YourUsername>`\n- C Filepath: `dna/src/dna.c`\n- Το πρόγραμμά σας θα πρέπει να παίρνει δύο ορίσματα από την γραμμή εντολών. Και τα δύο\n  θα είναι ονόματα αρχείων που περιέχουν τις εισόδους για το πρόγραμμα, δηλαδή τις δύο\n  αλυσίδες DNA - στην μορφή `./dna filename1 filename2`. Για το περιεχόμενο των αρχείων\n  δείτε παρακάτω. Αν δεν περαστούν δύο ορίσματα στην γραμμή εντολών ή οποιοδήποτε από\n  τα αρχεία δεν μπορεί να ανοιχτεί το πρόγραμμα πρέπει να επιστρέφει με κωδικό εξόδου\n  (exit code) 1.\n- Η βασική είσοδος για το πρόγραμμα θα είναι μέσω των περιεχομένων των αρχείων. Τα\n  αρχεία θα περιέχουν τις αλυσίδες DNA οι οποίες αποτελούνται από τους κεφαλαίους\n  χαρακτήρες A, G, T και C. Όλοι οι χαρακτήρες θα είναι σε μορφή ASCII, και το αρχείο θα\n  διαβάζεται και ως κείμενο. Οποιοσδήποτε χαρακτήρας εκτός από τους A, G, T, C πρέπει να\n  αγνοηθεί καθώς θεωρείται σφάλμα που δημιουργήθηκε κατά το\n  [sequencing](https://en.wikipedia.org/wiki/DNA_sequencing) της αλυσίδας.\n- Η έξοδος του προγράμματος θα πρέπει να είναι η μέγιστη κοινή αλυσίδα των δύο αλυσίδων\n  που δώσαμε ως είσοδο, ακολουθούμενη από μια καινούρια γραμμή. Όλα τα στοιχεία της\n  αλυσίδας εξόδου θα πρέπει να είναι βάσεις DNA - δεν επιτρέπονται άλλοι χαρακτήρες.\n  Εάν υπάρχουν πάνω από μία μέγιστη κοινή αλυσίδα, αρκεί να επιστραφεί μία από αυτές.\n- Το αρχείο C που θα υποβληθεί πρέπει να μεταγλωττίζεται χωρίς ειδοποιήσεις για λάθη\n  και με κωδικό επιστροφής (exit code) που να είναι 0. Συγκεκριμένα, το αρχείο σας\n  **πρέπει** να μπορεί να μεταγλωττιστεί επιτυχώς με την ακόλουθη εντολή σε ένα από τα\n  μηχανήματα του εργαστηρίου (linuxXY.di.uoa.gr):\n  `gcc -Ofast -m32 -Wall -Wextra -Werror -pedantic -o dna dna.c -lm`\n- README Filepath: `dna/README.md`\n- **Ένα αρχείο που να περιέχει στοιχεία εισόδου και ένα εξόδου διαφορετικά από αυτά\n  της άσκησης. Συγκεκριμένα προτείνουμε να βάλετε έναν συνδυασμό που θεωρείται ότι\n  είναι δύσκολος να γίνει σωστός.**\n  - input1 Filepath: `dna/test/input1.dna`\n  - input2 Filepath: `dna/test/input2.dna`\n  - output Filepath: `dna/test/output.dna`\n- Πρέπει να ολοκληρώνει την εκτέλεση μέσα σε: 90 δευτερόλεπτα.\n- Το μέγιστο μέγεθος επιτρεπτής αλυσίδας: 100.000 βάσεις.\n\nΠαρακάτω παραθέτουμε την αλληλεπίδραση με μια ενδεικτική λύση με μερικά δείγματα DNA\nπου κατεβάσαμε:\n\n```text\n$ gcc -Ofast -Wall -Wextra -Werror -pedantic -o dna dna.c -lm\n$ wc -c *.dna\n 62487 alien.dna\n  8193 carsonella-ruddii.dna\n 47811 claviceps-purpurea.dna\n 21992 escherichia-coli.dna\n    16 sample1.dna\n    16 sample2.dna\n 99492 theobroma-cacao.dna\n240007 total\n$ $./dna\nError: arguments missing. Usage: ./dna dnafile1 dnafile2\n$ echo $?\n1\n$ ./dna3 foo.bar bar.zonk\nError: cannot open file foo.bar\n$ echo $?\n1\n$ cat sample1.dna\nCATTAGATATAGACG\n$ cat sample2.dna\nCTATAGATATAGGGC\n$ ./dna sample1.dna sample2.dna\nTAGATATAG\n$ echo -e \"CTATAGAT\\nHello WORLDATAGGG\" > split.dna\n$ ./dna split.dna split.dna\nCTATAGATATAGGG\n$ ./dna carsonella-ruddii.dna sample1.dna\nATATAGACG\n$ ./dna escherichia-coli.dna carsonella-ruddii.dna\nAATTAAAATTTTATT\n$ ./dna claviceps-purpurea.dna carsonella-ruddii.dna\nGTTTTTTTTTTCT\n$ time ./dna theobroma-cacao.dna escherichia-coli.dna\nGGTTTGCTTTTATG\n\nreal 0m4.550s\nuser 0m4.549s\nsys 0m0.001s\n$ time ./dna theobroma-cacao.dna alien.dna\nAAAAAAAAAAAAAAAAACC\n\nreal 0m2.828s\nuser 0m2.827s\nsys 0m0.001s\n$ time ./dna theobroma-cacao.dna theobroma-cacao.dna > shared.dna\n\nreal 0m21.817s\nuser 0m21.815s\nsys 0m0.001s\n$ wc -c shared.dna\n98165 shared.dna\n$ md5sum shared.dna\n5ca8c9e6fd76d46221d3beadd610b165  shared.dna\n$ time ./dna alien.dna alien.dna > shared.dna\n\nreal 0m1.917s\nuser 0m1.915s\nsys 0m0.001s\n$ wc -c shared.dna\n62488 shared.dna\n$ md5sum shared.dna\nd4544ab6971c6a54bb375159adc5852b  shared.dna\n```\n\nΤα παραπάνω dna αρχεία είναι στο: <https://github.com/progintro/data/tree/main/dna>\nάλλα μπορείτε να δοκιμάσετε και άλλα παραδείγματα δικά σας. Στο αρχείο `README.md`\nπρέπει να προσθέσετε οποιεσδήποτε παρατηρήσεις σας κατά την διεκπεραίωση της άσκησης. Ο\nκώδικας απαιτείται να είναι καλά τεκμηριωμένος με σχόλια καθώς αυτό θα είναι μέρος της\nβαθμολόγησης.",
  "hint": "Πρόκειται για το πρόβλημα της μέγιστης κοινής *υποσυμβολοσειράς* (διαδοχικοί\nχαρακτήρες, όχι υποακολουθία). Φιλτράρετε πρώτα κάθε αρχείο σε μια καθαρή συμβολοσειρά\nμόνο με A, G, T, C, σε δυναμικά δεσμευμένη μνήμη. Μια σχέση του τύπου «μήκος κοινού\nτμήματος που τελειώνει στη θέση i της πρώτης και j της δεύτερης» δίνει λύση\nδυναμικού προγραμματισμού· ένας πλήρης πίνακας 100.000 × 100.000 όμως δεν χωράει στη\nμνήμη, οπότε σκεφτείτε ποιες γραμμές του χρειάζεστε πραγματικά κάθε στιγμή.\n\n## Δείτε επίσης\n\n- [Υποδειγματική υποβολή φοιτητή](https://progintro.github.io/samples/code/dna1/) (περιέχει λύση: δείτε την αφού λύσετε την άσκηση)"
 },
 {
  "id": "hw-2023-hw2-fauxtoshop",
  "kind": "homework",
  "title": "FauxtoShop: περιστροφή εικόνας BMP",
  "source": {
   "title": "Εργασία 2 (2023-24), Άσκηση 1",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2023/hw2.pdf",
   "years": [
    2023
   ]
  },
  "chapters": [
   12,
   13,
   18
  ],
  "topics": [
   "image-audio",
   "multidim-arrays",
   "dynamic-memory",
   "redirection"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α12.12",
  "path": "questions/homework/hw-2023-hw2-fauxtoshop.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2023-hw2-fauxtoshop.html",
  "statement": "Πολύ συχνά βγάζουμε φωτογραφίες που δεν έχουν τον σωστό προσανατολισμό και θέλουμε να\nτις περιστρέψουμε, χωρίς τους περιορισμούς (κόστος, μέγεθος εικόνας) των προγραμμάτων\nεπεξεργασίας εικόνας.\n\nΤο ζητούμενο σε αυτήν την άσκηση είναι να υλοποιήσουμε το δικό μας `fauxtoshop` που μας\nεπιτρέπει να περιστρέψουμε εικόνες τύπου\n[BMP (BitMaP)](https://en.wikipedia.org/wiki/BMP_file_format) δεξιόστροφα κατά 90° (με\nτην φορά του ρολογιού). Προκειμένου να το καταφέρουμε αυτό, θα χρειαστεί να μάθουμε λίγο\nπαραπάνω για την μορφή των αρχείων BMP. Σε αυτήν την άσκηση θα ασχοληθούμε με μια\nκατηγορία αρχείων BMP τα οποία έχουν την μορφή κεφαλίδων (headers) ακολουθούμενη από\nκάποια bytes και έναν δισδιάστατο πίνακα εικονοστοιχείων (pixels):\n\n```text\nHeaders (H bytes) | Other Data (M bytes) | Pixel 2-D array (N bytes)\n```\n\nΤα Σχήματα 1 και 2 της εκφώνησης παρουσιάζουν την ανάλυση των περιεχομένων ενός\nενδεικτικού αρχείου `color6x6.bmp`. Για τις ανάγκες της άσκησης, μπορείτε να υποθέσετε\nότι H ≥ 54 και ότι τα δεδομένα ανάμεσα στις κεφαλίδες Other Data δεν χρειάζονται αλλαγή\nαλλά πρέπει να αντιγραφούν όπως είναι.\n\n**Σχήμα 1** (τα 54 πρώτα bytes της κεφαλίδας, με την εντολή `xxd`):\n\n```text\n$ xxd -l 54 -g 1 -c 14 < color6x6.bmp\n00000000: 42 4d ae 00 00 00 00 00 00 00 36 00 00 00  BM........6...\n0000000e: 28 00 00 00 06 00 00 00 06 00 00 00 01 00  (.............\n0000001c: 18 00 00 00 00 00 78 00 00 00 c4 0e 00 00  ......x.......\n0000002a: c4 0e 00 00 00 00 00 00 00 00 00 00        ............\n```\n\nΤα σχόλια του σχήματος εξηγούν τα καίρια πεδία (απαραίτητα για την άσκηση):\n\n- Τα αρχεία bmp αρχίζουν με τους χαρακτήρες 'B' και 'M' (magic number 0x42 0x4d).\n- Στο 2ο byte της κεφαλίδας περιέχεται το μέγεθος του αρχείου (εδώ 174 bytes).\n- Στο 10ο byte της κεφαλίδας περιέχεται το offset του πίνακα των pixels σε μορφή little\n  endian (εδώ 54).\n- Στο 18ο byte της κεφαλίδας περιέχεται το πλάτος (width) της εικόνας σε pixels σε μορφή\n  little endian.\n- Στο 22ο byte της κεφαλίδας περιέχεται το ύψος (height) της εικόνας σε pixels σε μορφή\n  little endian.\n- Στο 34ο byte της κεφαλίδας περιέχεται το συνολικό μέγεθος της εικόνας σε bytes σε\n  μορφή little endian.\n\n**Σχήμα 2** (μόνο τα bytes των pixels, παραλείποντας τα 54 πρώτα):\n\n```text\n$ xxd -s 54 -c 20 -g 3 < color6x6.bmp\n00000036: 00ffff 00ffff 00ffff ff0000 ff0000 ff0000 0000\n0000004a: 00ffff 00ffff 00ffff ff0000 ff0000 ff0000 0000\n0000005e: 00ffff 00ffff 00ffff ff0000 ff0000 ff0000 0000\n00000072: 0000ff 0000ff 0000ff 00ff00 00ff00 00ff00 0000\n00000086: 0000ff 0000ff 0000ff 00ff00 00ff00 00ff00 0000\n0000009a: 0000ff 0000ff 0000ff 00ff00 00ff00 00ff00 0000\n```\n\nΚάθε pixel είναι 3 bytes με σειρά B, G, R. Κάθε γραμμή έχει στο τέλος 2 bytes padding\nώστε κάθε γραμμή να είναι πολλαπλάσιο του 4. Η πρώτη γραμμή του αρχείου είναι η κάτω\nγραμμή της εικόνας: το `pixels[0][0]` είναι το κάτω αριστερά pixel (κίτρινο) και το\n`pixels[4][1]` ένα κόκκινο pixel της πάνω αριστερά περιοχής. Η εικόνα έχει κίτρινο\nτεταρτημόριο κάτω αριστερά, μπλε κάτω δεξιά, κόκκινο πάνω αριστερά και πράσινο πάνω\nδεξιά. Δίνουμε **προσοχή στο padding** που μπορεί να έχει το κάθε αρχείο bmp το οποίο\nδεν έχει απεικόνιση για τους χρήστες.\n\n**Τεχνικές Προδιαγραφές**\n\n- Repository Name: `progintro/hw2-<YourUsername>`\n- C Filepath: `fauxtoshop/src/fauxtoshop.c`\n- Ένα αρχείο εισόδου/εξόδου BMP είναι δεκτό μόνο εάν:\n  - Ξεκινάει την μαγική κεφαλίδα με τα bytes: 'B' 'M'.\n  - Χρησιμοποιεί 24-bit για την αναπαράσταση χρώματος (μονοχρωματικά BMP δεν είναι\n    δεκτά).\n  - Χρησιμοποιεί τουλάχιστον 54 (14 + 40) bytes για την αναπαράσταση των κεφαλίδων\n    ακολουθώντας το Windows 3.x format (Bitmap file header + DIB header). Για\n    παράδειγμα, αρχεία που είναι συμβατά με την μορφή κεφαλίδας που δείχνουμε στο\n    Σχήμα 1 είναι δεκτά.\n  - Έχει σωστό μέγεθος αρχείου (τα μεγέθη στις κεφαλίδες συμφωνούν με τα περιεχόμενα\n    του αρχείου).\n  - Έχει σωστό μήκος, πλάτος και padding.\n- Το πρόγραμμά θα πρέπει να παίρνει είσοδο από το standard input. Για οποιαδήποτε\n  είσοδο δεν είναι μέσα στις προδιαγραφές το πρόγραμμα πρέπει να επιστρέφει με κωδικό\n  εξόδου (exit code) 1.\n- Ένα αρχείο `image.bmp` μπορεί να περαστεί στο πρόγραμμά μας με ανακατεύθυνση\n  (redirection) στο stdin και αντίστοιχα η έξοδος μπορεί να γραφτεί σε ένα αρχείο\n  `rotated.bmp` και πάλι με ανακατεύθυνση του stdout:\n  `$ ./fauxtoshop < image.bmp > rotated.bmp`\n- Το αρχείο C που θα υποβληθεί πρέπει να μεταγλωττίζεται χωρίς ειδοποιήσεις για λάθη\n  και με κωδικό επιστροφής (exit code) που να είναι 0. Συγκεκριμένα, το αρχείο σας\n  **πρέπει** να μπορεί να μεταγλωττιστεί επιτυχώς με την ακόλουθη εντολή σε ένα από τα\n  μηχανήματα του εργαστηρίου (linuxXY.di.uoa.gr):\n  `gcc -O3 -Wall -Wextra -Werror -pedantic -o fauxtoshop fauxtoshop.c`\n- README Filepath: `fauxtoshop/README.md`\n- **Ένα αρχείο που να περιέχει στοιχεία εισόδου και ένα εξόδου διαφορετικά από αυτά\n  της άσκησης. Συγκεκριμένα προτείνουμε να βάλετε έναν συνδυασμό που θεωρείται ότι\n  είναι δύσκολος να γίνει σωστός.**\n  - input Filepath: `fauxtoshop/test/input.bmp`\n  - output Filepath: `fauxtoshop/test/output.bmp`\n- Πρέπει να ολοκληρώνει την εκτέλεση μέσα σε: 10 δευτερόλεπτα.\n- **Δεν επιτρέπεται** η χρήση δομών/εγγραφών (`struct`).\n\nΠαρακάτω παραθέτουμε την αλληλεπίδραση με μια ενδεικτική λύση (το Σχήμα 3 της\nεκφώνησης δείχνει την εικόνα `Apparition_of_Face_and_Fruit.bmp` πριν και μετά την\nπεριστροφή):\n\n```text\n$ gcc -O3 -Wall -Wextra -Werror -pedantic -o fauxtoshop fauxtoshop.c\n$ ./fauxtoshop < ./fauxtoshop\nError: not a BMP file\n$ echo $?\n1\n$ ./fauxtoshop < color6x6.bmp > color6x6.90.bmp\n$ ./fauxtoshop < color6x6.90.bmp > color6x6.180.bmp\n$ ./fauxtoshop < color6x6.180.bmp > color6x6.270.bmp\n$ ./fauxtoshop < color6x6.270.bmp > color6x6.360.bmp\n$ md5sum color6x6*.bmp\n755c07991c51c0b3af855ba7f668c7d0  color6x6.180.bmp\n5f19168fa9511a6520ec5dba2db4b478  color6x6.270.bmp\n33855d8642cf110f74464f8ff78449aa  color6x6.360.bmp\n6d62a0c4264dbfa962b372b6e5c8b9be  color6x6.90.bmp\n33855d8642cf110f74464f8ff78449aa  color6x6.bmp\n$ wc -c color6x6*.bmp\n174 color6x6.180.bmp\n174 color6x6.270.bmp\n174 color6x6.360.bmp\n174 color6x6.90.bmp\n174 color6x6.bmp\n$ ./fauxtoshop < Apparition_of_Face_and_Fruit.bmp > app90.bmp\n$ md5sum Apparition_of_Face_and_Fruit.bmp app90.bmp\n841d3634ba8c6af641d86b63ac1b6dfc  Apparition_of_Face_and_Fruit.bmp\n96e8c33582f8a922a6665d4891e62a77  app90.bmp\n$ wc -c Apparition_of_Face_and_Fruit.bmp app90.bmp\n1440054 Apparition_of_Face_and_Fruit.bmp\n1440054 app90.bmp\n2880108 total\n$ ./fauxtoshop < school_of_athens.bmp > school_of_athens90.bmp\n$ md5sum school_of_athens*.bmp\n282d01bbd23044a7e6ca91f0dda2238f  school_of_athens90.bmp\n112ce7f3a60265992dc939949232257d  school_of_athens.bmp\n$ wc -c school_of_athens*.bmp\n15252534 school_of_athens.bmp\n15257654 school_of_athens90.bmp\n30510188 total\n$ file school_of_athens.bmp school_of_athens90.bmp\nschool_of_athens.bmp:   PC bitmap, Windows 3.x format, 2560 x 1986 x 24,\n                        image size 15252480, cbSize 15252534, bits offset 54\nschool_of_athens90.bmp: PC bitmap, Windows 3.x format, 1986 x 2560 x 24,\n                        image size 15257600, cbSize 15257654, bits offset 54\n$ ./fauxtoshop < school_of_athens.bmp |./fauxtoshop | ./fauxtoshop |\n          ./fauxtoshop > school_of_athens360.bmp\n$ md5sum school_of_athens*.bmp\n112ce7f3a60265992dc939949232257d  school_of_athens360.bmp\n282d01bbd23044a7e6ca91f0dda2238f  school_of_athens90.bmp\n112ce7f3a60265992dc939949232257d  school_of_athens.bmp\n```\n\nΤα παραπάνω bmp αρχεία είναι στο: <https://github.com/progintro/data/tree/main/bmp>\nάλλα μπορείτε να δοκιμάσετε και άλλα παραδείγματα εικόνων που βρίσκετε online. Εκτός από\n`scp` για να τα αντιγράψετε στο Linux lab, μπορείτε να τα κατεβάσετε και μέσω κονσόλας\nχρησιμοποιώντας `curl`, για παράδειγμα:\n\n```text\n$ curl -O https://raw.githubusercontent.com/progintro/data/main/bmp/color6x6.bmp\n```\n\nΩς συνήθως, στο αρχείο `README.md` πρέπει να προσθέσετε οποιεσδήποτε παρατηρήσεις σας\nκατά την διεκπεραίωση της άσκησης. Ο κώδικας απαιτείται να είναι καλά τεκμηριωμένος με\nσχόλια καθώς αυτό θα είναι μέρος της βαθμολόγησης.",
  "hint": "Διαβάστε ολόκληρο το stdin σε έναν δυναμικά δεσμευμένο πίνακα από `unsigned char` και\nγράψτε μια βοηθητική συνάρτηση που διαβάζει ακέραιο 4 bytes σε little endian από\nδοσμένο offset. Υπολογίστε το μέγεθος κάθε γραμμής με το padding (στρογγυλοποίηση του\n3·width στο επόμενο πολλαπλάσιο του 4) για την είσοδο *και* για την έξοδο, όπου πλάτος\nκαι ύψος αλλάζουν θέση· ενημερώστε στην κεφαλίδα της εξόδου πλάτος, ύψος, μέγεθος\nεικόνας και αρχείου. Δουλέψτε πρώτα την αντιστοίχιση θέσεων (γραμμή, στήλη) στο χαρτί με\nτη μικρή `color6x6.bmp`, θυμηθείτε ότι οι γραμμές αποθηκεύονται από κάτω προς τα πάνω,\nκαι δοκιμάστε με μια εικόνα μη τετράγωνη με πλάτος που δεν είναι πολλαπλάσιο του 4.\n\n## Δείτε επίσης\n\n- [Υποδειγματική υποβολή φοιτητή](https://progintro.github.io/samples/code/fauxtoshop1/) (περιέχει λύση: δείτε την αφού λύσετε την άσκηση)"
 },
 {
  "id": "hw-2023-hw3-fractal",
  "kind": "homework",
  "title": "Η Newton-Raphson Ξαναχτυπά! (Bonus)",
  "source": {
   "title": "Εργασία 3 (2023-24), Άσκηση 2 (Bonus) και 2.1 (Bonus)",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2023/hw3.pdf",
   "years": [
    2023
   ]
  },
  "chapters": [
   23,
   19,
   18
  ],
  "topics": [
   "structs",
   "code-organization",
   "floating-point",
   "files",
   "image-audio"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α23.6",
  "path": "questions/homework/hw-2023-hw3-fractal.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2023-hw3-fractal.html",
  "statement": "Στην Εργασία 1 δοκιμάσαμε να γράψουμε ένα πρόγραμμα που\nέβρισκε αυτόματα ρίζες σε πολυώνυμα, αλλά δυστυχώς δεν είχαν όλα τα πολυώνυμα ρίζες. Για\nπαράδειγμα, το πολυώνυμο $x^2 + 1$ δεν είχε ρίζες καθώς η διακρίνουσα είναι αρνητική.\nΜε τους [φανταστικούς αριθμούς](https://en.wikipedia.org/wiki/Imaginary_number) όμως,\nόπου η φανταστική μονάδα $i$ όταν υψωθεί στο τετράγωνο μας κάνει −1 ($i^2 = -1$),\nμπορούμε να πούμε ότι το $x = i$ είναι μια ρίζα του παραπάνω πολυωνύμου. Αντίστοιχα,\nμπορεί η ρίζα ενός πολυωνύμου να είναι ένας συνδυασμός πραγματικών και φανταστικών,\nδηλαδή κάτι που ονομάζεται μιγαδικός αριθμός\n([complex number](https://en.wikipedia.org/wiki/Complex_number)).\n\nΘα δοκιμάσουμε να βρούμε λύσεις σε πολυώνυμα στο μιγαδικό επίπεδο. Η μέθοδος Newton\nπαραμένει η ίδια, απλά αλλάζουμε τον ορισμό του τύπου που παίρνει η f: Δεδομένης μιας\nμιγαδικής συνάρτησης $f(z)$ και της παραγώγου της $f'(z)$, ξεκινώντας με ένα τυχαίο\n$z_0$ μία καλύτερη προσέγγιση μιας ρίζας του πολυωνύμου $z_1$ δίνεται από την σχέση:\n\n$$z_1 = z_0 - \\frac{f(z_0)}{f'(z_0)}$$\n\nΑντίστοιχα, η γενική αναδρομική σχέση της μεθόδου του Νεύτωνα είναι:\n\n$$z_{n+1} = z_n - \\frac{f(z_n)}{f'(z_n)}$$\n\nόπου $z_{n+1}$ είναι η προσεγγιστική τιμή μιας ρίζας της συνάρτησης $f(z)$ μετά από\n$n + 1$ επαναλήψεις. Σε αντίθεση με την προηγούμενη άσκηση, *όλες οι πράξεις* που\nκάναμε με αριθμούς κινητής υποδιαστολής και μας δίνονταν ως βασικοί τελεστές (built in\nprimitives/operators), τώρα θα πρέπει να οριστούν και να υλοποιηθούν για complex\nαριθμούς. Κάποιες από τις βασικές πράξεις για μιγαδικούς που μπορεί να χρειαστείτε\nπεριλαμβάνουν (ελέγξτε την ορθότητά τους για την αποφυγή ορθογραφικών με άλλες πηγές):\n\n$$(a + bi) + (c + di) = (a + c) + (b + d)i$$\n\n$$(a + bi) \\cdot (c + di) = (ac - bd) + (ad + bc)i$$\n\n$$\\frac{a + bi}{c + di} = \\frac{ac + bd}{c^2 + d^2} + \\frac{bc - ad}{c^2 + d^2}i$$\n\n$$|a + bi| = \\sqrt{a^2 + b^2}$$\n\nΓια κάθε αρχικό $z_0$, η μέθοδος Newton μπορεί να βρει μια ρίζα του πολυωνύμου - χωρίς\nνα μπορούμε να προβλέψουμε ποια - και οι υπόλοιπες ρίζες μας διαφεύγουν. Μια συχνή λύση\nγια να βρούμε περισσότερες ρίζες είναι να δοκιμάσουμε πολλά και διαφορετικά $z_0$ και να\nτρέξουμε πολλές φορές την μέθοδο Newton.\n\nΓια το ζητούμενο αυτής της άσκησης, καλείστε να γράψετε ένα πρόγραμμα που υπολογίζει\nαυτόματα τις ρίζες (τα z για τα οποία μηδενίζεται) *οποιουδήποτε* πολυωνύμου για ένα\nσύνολο από μιγαδικούς προκειμένου να μπορούμε να εντοπίσουμε περισσότερες από μία ρίζες.\n\n**Τεχνικές Προδιαγραφές**\n\n- Repository Name: `progintro/hw3-<YourTeamName>`\n- Σε αντίθεση με όλες τις άλλες ασκήσεις μέχρι τώρα όπου όλος ο κώδικας του\n  προγράμματός μας ήταν σε ένα αρχείο, σε αυτήν την εργασία, ο κώδικάς σας θα πρέπει να\n  είναι χωρισμένος σε πολλά αρχεία και συγκεκριμένα:\n  1. C Filepath: `fractal/src/complexlib.c` - το αρχείο στο οποίο θα βρίσκεται η\n     υλοποίηση για όλες τις βασικές πράξεις με μιγαδικούς: πρόσθεση, αφαίρεση, διαίρεση\n     κτλ.\n  2. Header Filepath: `fractal/src/complexlib.h` - το αρχείο κεφαλίδων στο οποίο θα\n     βρίσκονται οι δηλώσεις όλων των βασικών συναρτήσεων μιγαδικών που υλοποιήσατε.\n  3. C Filepath: `fractal/src/fractal.c` - το αρχείο στο οποίο θα βρίσκεται η `main`\n     σας και θα κάνει include το `\"complexlib.h\"` προκειμένου να χρησιμοποιήσει όλες τις\n     συναρτήσεις μιγαδικών που θα χρειαστείτε.\n- Το πρόγραμμά θα πρέπει να παίρνει ως πρώτο και κύριο όρισμα από την γραμμή εντολών το\n  όνομα ενός αρχείου που περιέχει την είσοδο για το πρόγραμμα - στην μορφή\n  `./fractal filename`. Για το περιεχόμενο του αρχείου δείτε παρακάτω. Αν το αρχείο δεν\n  μπορεί να ανοιχτεί το πρόγραμμα πρέπει να επιστρέφει με κωδικό εξόδου (exit code) 1.\n- Η βασική είσοδος για το πρόγραμμα θα είναι μέσω των περιεχομένων του αρχείου (το\n  όνομα του αρχείου θα δίνεται ως πρώτο όρισμα όπως αναφέρθηκε παραπάνω). Το αρχείο θα\n  έχει την ακόλουθη μορφή:\n\n  ```text\n  POLYNOMIAL_DEGREE_N\n  A0 A1 A2 ... AN\n  MIN_REAL MIN_IMAG MAX_REAL MAX_IMAG STEP\n  ```\n\n  Η πρώτη γραμμή περιέχει τον βαθμό του πολυωνύμου. Η δεύτερη περιέχει τους\n  πραγματικούς όρους του πολυωνύμου γραμμένους ως double. Η τρίτη και τελευταία γραμμή\n  περιέχει δύο double όρους που καθορίζουν το παράθυρο μέσα στο οποίο θα αναζητήσουμε\n  λύσεις με την μέθοδο Newton (δες παρακάτω στην ενδεικτική λύση). Για παράδειγμα, για\n  ένα πολυώνυμο 5ου βαθμού $0.0 + 1.0x + 2.0x^2 + 3.0x^3 + 4.0x^4 + 5.0x^5$ και μέγεθος\n  παραθύρου το $[-1.0 - i, 1.01 + 1.01i]$ με βήμα 0.1 η είσοδος θα είναι:\n\n  ```text\n  5\n  0.0 1.0 2.0 3.0 4.0 5.0\n  -1.0 -1.0 1.01 1.01 0.1\n  ```\n\n- Όλες οι παράμετροι θα είναι σε δεκαδική μορφή τύπου `double` και επαρκούς ακρίβειας\n  ώστε να χωράνε σε μεταβλητές double. Συνιστούμε να χρησιμοποιήσετε την συνάρτηση\n  βιβλιοθήκης `fscanf` για να διαβάσετε τους αριθμούς από το αρχείο με τους κατάλληλους\n  μετατροπείς.\n- Η λύση σας πρέπει να κάνει χρήση ενός τύπου `complex` προκειμένου να μοντελοποιήσει\n  τους μιγαδικούς αριθμούς. Περιμένουμε ότι ο ορισμός του τύπου θα έχει αυτήν την μορφή:\n\n  ```c\n  typedef struct {\n    double real;\n    double imag;\n  } complex;\n  ```\n\n- Το αρχείο C που θα υποβληθεί πρέπει να μεταγλωττίζεται χωρίς ειδοποιήσεις για λάθη\n  και με κωδικό επιστροφής (exit code) που να είναι 0. Συγκεκριμένα, το αρχείο σας\n  **πρέπει** να μπορεί να μεταγλωττιστεί επιτυχώς με τις ακόλουθες εντολές σε ένα από\n  τα μηχανήματα του εργαστηρίου (linuxXY.di.uoa.gr):\n\n  ```text\n  gcc -Ofast -Wall -Wextra -Werror -pedantic -c -o complexlib.o complexlib.c\n  gcc -Ofast -Wall -Wextra -Werror -pedantic -c -o fractal.o fractal.c\n  gcc -o fractal complexlib.o fractal.o -lm\n  ```\n\n- README Filepath: `fractal/README.md`\n- **Ένα αρχείο που να περιέχει στοιχεία εισόδου και ένα εξόδου διαφορετικά από αυτά\n  της άσκησης. Συγκεκριμένα προτείνουμε να βάλετε έναν συνδυασμό που θεωρείται ότι\n  είναι δύσκολος να γίνει σωστός.**\n  - input Filepath: `fractal/test/input`\n  - output Filepath: `fractal/test/output`\n- Όλες οι μιγαδικές λύσεις θα πρέπει να είναι δεκαδικοί με δύο ψηφία ακριβείας και\n  πρόσημο.\n- Συνθήκες τερματισμού: ο αλγόριθμος πρέπει να τερματίσει *όταν*:\n  1. Ο αλγόριθμος έχει συγκλίνει και ισχύει: $|z_{n+1} - z_n| < 10^{-6}$. Σε αυτήν την\n     περίπτωση τυπώνουμε το αποτέλεσμα $z_{n+1}$ με ακρίβεια δύο δεκαδικών ψηφίων και\n     πρόσημο για κάθε μέρος του μιγαδικού.\n  2. Ο αλγόριθμος αποκλίνει (π.χ., διαίρεση με 0). Σε αυτήν την περίπτωση τυπώνουμε το\n     αποτέλεσμα `nan`.\n  3. Ο αλγόριθμος δεν τερματίζει μετά από 1000 επαναλήψεις. Σε αυτήν την περίπτωση\n     τυπώνουμε το αποτέλεσμα `incomplete`.\n- Πρέπει να ολοκληρώνει την εκτέλεση μέσα σε: 60 δευτερόλεπτα.\n- Μέγιστος βαθμός πολυωνύμου: 10.\n- Μέγιστος αριθμός στοιχείων του πίνακα που ζητάμε να εκτυπωθεί (για πόσα διαφορετικά\n  $z_0$ να τρέξουμε την Newton Raphson): 10^6, π.χ., 1000 × 1000.\n- **Δεν επιτρέπεται** η χρήση των built in complex αριθμών, π.χ., όπως ορίζονται στο\n  `complex.h`, η χρήση του τύπου `_Complex` κτλ. Θέλουμε όλες οι πράξεις να οριστούν από\n  εσάς και να βασίζονται στον τύπο `complex` που ορίσαμε παραπάνω.\n\nΈστω ότι θέλουμε να βρούμε τις λύσεις της Newton-Raphson για το πολυώνυμο\n$1 + z - z^3 + z^4$ για τα ακόλουθα $z_0$:\n$\\{-1 - i, -1 + 0i, -1 + i, 0 - i, 0, 0 + i, 1 - i, 1, 1 + i\\}$, δηλαδή θέλουμε να\nσαρώσουμε όλους τους μιγαδικούς από το $-1 - i$ μέχρι το $1 + i$ με βήμα 1. Παρακάτω\nπαραθέτουμε την αλληλεπίδραση με μια ενδεικτική λύση:\n\n```text\n$ cat input\n4\n1.0 1.0 0.0 -1.0 1.0\n-1.0 -1.0 1.01 1.01 1.0\n$ ./fractal input\n-0.57-0.46i incomplete -0.57+0.46i\n+1.07-0.86i incomplete +1.07+0.86i\n+1.07-0.86i incomplete +1.07+0.86i\n```\n\nόπου βλέπουμε ότι για $z_0 = -1 - i$ (το πρώτο στοιχείο της πρώτης σειράς) η Newton\nσυγκλίνει στην ρίζα $-0.57 - 0.46i$, ενώ για $z_0 = 0$ το αποτέλεσμα είναι incomplete\n(το 2ο στοιχείο της 2ης σειράς). Επομένως το αποτέλεσμα είναι ένας δισδιάστατος πίνακας\nμε τις ρίζες στις οποίες αποτιμάται το πολυώνυμο για τα διάφορα $z_0$:\n\n| real/imag | -i | 0i | 1i |\n| --- | --- | --- | --- |\n| -1 | -0.57-0.46i | incomplete | -0.57+0.46i |\n| +0 | +1.07-0.86i | incomplete | +1.07+0.86i |\n| +1 | +1.07-0.86i | incomplete | +1.07+0.86i |\n\nΤο Σχήμα 3 της εκφώνησης δείχνει τα Newton fractals για το πολυώνυμο\n$1 + z - z^3 + z^4$ από το $-2 - 2i$ μέχρι το $+2 + 2i$, και το ίδιο fractal με βήμα 5×\nμικρότερο: κάθε ρίζα έχει δικό της χρώμα.\n\nΑντίστοιχα μπορούμε να αυξήσουμε την πυκνότητα των αποτελεσμάτων που ελέγχουμε σε ένα\nπαράθυρο, μειώνοντας το βήμα (τους μιγαδικούς στο $[-0.2 + 0.2i, 0.21 + 0.51i]$ με βήμα\n0.05). Για παράδειγμα:\n\n```text\n$ cat input\n4\n1.0 1.0 0.0 -1.0 1.0\n-0.2 0.2 0.21 0.51 0.05\n$ ./fractal input\n-0.57+0.46i -0.57+0.46i -0.57+0.46i -0.57+0.46i -0.57+0.46i -0.57+0.46i -0.57+0.46i\n-0.57+0.46i -0.57+0.46i -0.57+0.46i -0.57+0.46i -0.57+0.46i -0.57+0.46i -0.57+0.46i\n-0.57+0.46i -0.57+0.46i -0.57+0.46i -0.57+0.46i -0.57+0.46i -0.57+0.46i -0.57+0.46i\n+1.07-0.86i -0.57+0.46i -0.57+0.46i -0.57+0.46i +1.07+0.86i -0.57-0.46i -0.57-0.46i\n-0.57-0.46i +1.07-0.86i -0.57-0.46i -0.57-0.46i -0.57-0.46i -0.57-0.46i +1.07+0.86i\n-0.57+0.46i -0.57-0.46i -0.57-0.46i -0.57-0.46i -0.57-0.46i -0.57-0.46i -0.57-0.46i\n-0.57-0.46i -0.57-0.46i -0.57-0.46i -0.57-0.46i -0.57-0.46i -0.57-0.46i -0.57-0.46i\n-0.57-0.46i -0.57-0.46i -0.57-0.46i -0.57-0.46i -0.57-0.46i -0.57-0.46i -0.57-0.46i\n-0.57-0.46i -0.57-0.46i -0.57-0.46i -0.57-0.46i -0.57-0.46i -0.57-0.46i -0.57-0.46i\n```\n\nΑν κοιτάξουμε προσεκτικά το παραπάνω βλέπουμε 4 διαφορετικές λύσεις, τις:\n$-0.57 - 0.46i$, $-0.57 + 0.46i$, $+1.07 + 0.86i$ και $+1.07 - 0.86i$ (πράγματι\nπαρατηρούμε ότι $f(-0.57 - 0.46i) = -0.00 - 0.00i$) και επομένως καταφέραμε να βρούμε\nκαι τις τέσσερις ρίζες αυτού του πολυωνύμου! Η μόνη δυσκολία ίσως βρίσκεται στο να\nβρούμε τις περιοχές των μιγαδικών που πρέπει να σκανάρουμε.\n\nΣτο αρχείο `README.md` πρέπει να προσθέσετε οποιεσδήποτε παρατηρήσεις σας κατά την\nδιεκπεραίωση της άσκησης. Ο κώδικας απαιτείται να είναι καλά τεκμηριωμένος με σχόλια\nκαθώς αυτό θα είναι μέρος της βαθμολόγησης.\n\n### 2.1 Newton Fractals (Bonus 50 Μονάδες)\n\nΑν συνεχίσουμε να μειώνουμε το βήμα από την είσοδο του fractal παραπάνω οι πίνακες\nγίνονται μεγάλοι γρήγορα και αυξάνοντας την ανάλυση (resolution) των αποτελεσμάτων\nβλέπουμε πως μια μικρή αλλαγή της τάξης του 0.01 σε μια διάσταση μπορεί να κάνει την\nμέθοδο Newton να συγκλίνει σε διαφορετική ρίζα. Αν πειραματιστούμε αρκετά και έχουμε\nυπομονή μπορεί να παρατηρήσουμε ότι οι ρίζες προκύπτουν επαναλαμβανόμενα με μια\nκανονικότητα που θυμίζει [fractal](https://en.wikipedia.org/wiki/Fractal). Ένας τρόπος να\nοπτικοποιήσουμε αυτήν την κανονικότητα είναι να δώσουμε ένα χρώμα στην κάθε διαφορετική\nλύση στην οποία συγκλίνει η Newton-Raphson και να βάλουμε όλα αυτά τα χρώματα σε ένα\nδισδιάστατο επίπεδο που αναπαριστά τις αρχικές τιμές του $z_0$ στο πεδίο των μιγαδικών.\nΤα fractal που δημιουργούνται με αυτήν την μέθοδο λέγονται\n[Newton Fractals](https://en.wikipedia.org/wiki/Newton_fractal). (Το Σχήμα 4 της\nεκφώνησης δείχνει ένα Newton fractal για το $z^4 - 1$, όπου το βάθος των χρωμάτων\nυποδεικνύει πόσο γρήγορα συγκλίνει, σε αριθμό επαναλήψεων, το κάθε σημείο σε μια ρίζα.)\n\nΣε αυτήν την επέκταση της προηγούμενης άσκησης, ο στόχος είναι να προσθέσετε την\nδυνατότητα στο πρόγραμμά σας να δημιουργεί fractal visualizations.\n\n**Τεχνικές Προδιαγραφές (Επέκταση της λύσης fractal)**\n\n- Εκτός από το πρώτο και κύριο όρισμα (το αρχείο με την είσοδο για το πολυώνυμο), το\n  πρόγραμμά σας θα πρέπει να μπορεί να αναγνωρίζει δύο ακόμα προαιρετικά ορίσματα\n  `\"-g output.bmp\"`, δηλαδή το όρισμα `\"-g\"` που ορίζει ότι θέλουμε graphical output και\n  το όρισμα που το ακολουθεί - π.χ., `\"output.bmp\"` - το οποίο είναι το αρχείο στο οποίο\n  θέλουμε να σώσουμε την οπτικοποίηση του fractal μας.\n- Filepath: `fractal/data/input`. Ένα αρχείο με πολυώνυμο που δοκιμάσατε να\n  οπτικοποιήσετε.\n- Filepath: `fractal/data/output.bmp`. Το αρχείο από Newton Fractal που οπτικοποίησε το\n  πρόγραμμά σας για το παραπάνω input.",
  "hint": "Ξεκινήστε από τη βιβλιοθήκη: ορίστε τον `complex` στο `complexlib.h` (με include guard)\nμαζί με τα πρωτότυπα, υλοποιήστε και ελέγξτε κάθε πράξη χωριστά, και μόνο μετά γράψτε\nτη Newton στο `fractal.c`. Υπολογίστε το πολυώνυμο και την παράγωγό του με τον κανόνα του\nHorner πάνω σε μιγαδικούς, και προσέξτε τη σειρά σάρωσης: κάθε γραμμή της εξόδου\nαντιστοιχεί σε ένα πραγματικό μέρος και κάθε στήλη σε ένα φανταστικό. Προσέξτε επίσης το\n«μείον μηδέν» στην εκτύπωση και τη συσσώρευση σφάλματος όταν προσθέτετε το βήμα\nεπανειλημμένα· για το bonus, ξαναχρησιμοποιήστε ό,τι μάθατε για τη μορφή BMP στο\nfauxtoshop."
 },
 {
  "id": "hw-2023-hw3-zoomba",
  "kind": "homework",
  "title": "Zoomba: συντομότερη διαδρομή σε δωμάτιο",
  "source": {
   "title": "Εργασία 3 (2023-24), Άσκηση 1",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2023/hw3.pdf",
   "years": [
    2023
   ]
  },
  "chapters": [
   22,
   13,
   12
  ],
  "topics": [
   "graphs",
   "multidim-arrays",
   "dynamic-memory",
   "input-validation"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α22.15",
  "path": "questions/homework/hw-2023-hw3-zoomba.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2023-hw3-zoomba.html",
  "statement": "Η Εργασία 3 είναι προαιρετικά ομαδική (ομάδες μέχρι 2 άτομα) και κάθε repository πρέπει\nνα έχει ένα αρχείο `AUTHORS` με μία γραμμή για κάθε άτομο (sdi, GitHub username, όνομα).\n\nΟι ρομποτικές σκούπες Roomba κάνουν τυχαίες βόλτες στον χώρο αντί να πάνε κατευθείαν\nστο σημείο που χρειάζεται καθάρισμα, με αποτέλεσμα να κολλάνε (Σχήμα 1 της εκφώνησης) ή\nνα αδειάζει η μπαταρία τους. Η δική μας ρομποτική σκούπα, η Zoomba, διαθέτει ραντάρ που\nσκανάρει το δωμάτιο, δημιουργεί τον \"χάρτη\" του και εντοπίζει το σημείο που χρειάζεται\nεπειγόντως καθαρισμό. Αυτό που μας λείπει είναι ένα υποσύστημα που παίρνει τον χάρτη του\nδωματίου και το σημείο-στόχο καθαρισμού και επιστρέφει τις κινήσεις που πρέπει να\nακολουθήσει η Zoomba μας. Η γραφή αυτού του υποσυστήματος είναι το ζητούμενο αυτής της\nάσκησης.\n\n**Τεχνικές Προδιαγραφές**\n\n- Repository Name: `progintro/hw3-<YourTeamName>`\n- README Filepath: `zoomba/README.md`\n- C Filepath: `zoomba/src/zoomba.c`\n- Το πρόγραμμα θα πρέπει να δέχεται από την πρότυπη είσοδο (stdin) τα δεδομένα του\n  δωματίου στο οποίο βρίσκεται. Συγκεκριμένα, η είσοδος θα έχει την ακόλουθη γενική\n  μορφή:\n\n  ```text\n  ROOM_DIMENSION_N\n  ZOOMBA_X ZOOMBA_Y ZOOMBA_TARGET_X ZOOMBA_TARGET_Y\n  ROOM_ENCODED_AS_1s_AND_0s\n  ```\n\n  Η πρώτη γραμμή θα περιέχει την διάσταση του τρέχοντος δωματίου ως ακέραιο (μόνο\n  τετράγωνα δωμάτια είναι δεκτά για το πρωτότυπό μας), την τρέχουσα θέση της zoomba σε\n  καρτεσιανές συντεταγμένες (ακέραιοι), την θέση στόχο την οποία πρέπει να καθαρίσει σε\n  καρτεσιανές συντεταγμένες (ακέραιοι) και τέλος τον χάρτη του τρέχοντος δωματίου\n  κωδικοποιημένο ως 1 και 0 - όπου 1 δηλώνει την παρουσία κάποιου εμποδίου ενώ 0\n  δηλώνει ανοιχτό χώρο. Οποιαδήποτε είσοδος δεν ακολουθεί την παραπάνω μορφή θα πρέπει\n  να κάνει το πρόγραμμα να τερματίζει με κωδικό εξόδου (exit code) 1. Ομοίως και αν οι\n  συντεταγμένες που δόθηκαν είναι λανθασμένες - για παράδειγμα αν η θέση της zoomba ή\n  του στόχου είναι πάνω σε εμπόδιο - το πρόγραμμα πρέπει να τερματίζει με κωδικό εξόδου\n  1. Για παράδειγμα, μια πιθανή είσοδος είναι η ακόλουθη - μπορείτε να την συγκρίνετε με\n  την απεικόνιση στο Σχήμα 2:\n\n  ```text\n  10\n  1 8 8 1\n  0000000000\n  0110000000\n  0110000000\n  0100000000\n  0110000000\n  0111111100\n  0000000000\n  0000000000\n  0000001110\n  0000000000\n  ```\n\n  Το Σχήμα 2 της εκφώνησης δείχνει τον χάρτη ως πλέγμα 10 × 10 με τα εμπόδια, την\n  αρχική θέση της Zoomba (ένα γρανάζι, πάνω δεξιά) και την περιοχή που χρειάζεται\n  καθάρισμα (κόκκινο X, κάτω αριστερά). Μια από τις λύσεις που θέλουμε να επιλέξει η\n  Zoomba αποτελείται από 14 βήματα: `DDDDDDLLLLLLLD`. Παρατηρήστε ότι υπάρχουν πάνω από\n  μία βέλτιστες λύσεις.\n\n- Στην έξοδό του το πρόγραμμά σας πρέπει να τυπώνει τις κινήσεις που πρέπει να\n  πραγματοποιήσει η zoomba προκειμένου να φτάσει στον στόχο στην πρότυπη έξοδο\n  (stdout). Για εξοικονόμηση υλικών, η zoomba μας μπορεί να κινηθεί μόνο πάνω (U - Up),\n  κάτω (D - Down), αριστερά (L - Left) και δεξιά (R - Right) οπότε όλες οι λύσεις\n  πρέπει να εκφραστούν με αυτούς τους τέσσερις χαρακτήρες. Η λύση **πρέπει να είναι η\n  συντομότερη δυνατή σε αριθμό κινήσεων** της zoomba (θεωρούμε ότι όλες οι κινήσεις\n  έχουν το ίδιο ενεργειακό κόστος). Για παράδειγμα, η λύση που εικονίζεται στο Σχήμα 2\n  θα έχει την ακόλουθη μορφή:\n\n  ```text\n  DDDDDDLLLLLLLD\n  ```\n\n  Παρατηρήστε ότι είναι η βέλτιστη από απόψεως αριθμού κινήσεων - φτάνει στον στόχο\n  μόλις σε 14 βήματα. Αφού τυπώσει την λύση, το πρόγραμμα πρέπει να τερματίζει με κωδικό\n  εξόδου (exit code) 0. Εάν δεν υπάρχει καμία λύση επειδή η θέση δεν είναι προσβάσιμη,\n  το πρόγραμμά μας πρέπει να τυπώνει \"0\" και πάλι να τερματίζει με κωδικό εξόδου 0.\n- Το αρχείο C που θα υποβληθεί πρέπει να μεταγλωττίζεται χωρίς ειδοποιήσεις για λάθη\n  και με κωδικό επιστροφής (exit code) που να είναι 0. Συγκεκριμένα, το αρχείο σας\n  **πρέπει** να μπορεί να μεταγλωττιστεί επιτυχώς με την ακόλουθη εντολή σε ένα από τα\n  μηχανήματα του εργαστηρίου (linuxXY.di.uoa.gr):\n  `gcc -Ofast -Wall -Wextra -Werror -pedantic -o zoomba zoomba.c -lm`\n- **Ένα αρχείο που να περιέχει στοιχεία εισόδου και ένα εξόδου διαφορετικά από αυτά\n  της άσκησης. Συγκεκριμένα προτείνουμε να βάλετε έναν συνδυασμό που θεωρείται ότι\n  είναι δύσκολος να γίνει σωστός.**\n  - input Filepath: `zoomba/test/input`\n  - output Filepath: `zoomba/test/output`\n- Μέγιστη διάσταση δωματίου: 10000.\n- Πρέπει να ολοκληρώνει την εκτέλεση μέσα σε: 30 δευτερόλεπτα.\n\nΠαρακάτω παραθέτουμε την αλληλεπίδραση με μια ενδεικτική λύση:\n\n```text\n$ echo | ./zoomba\nIncorrect room input provided.\n$ echo $?\n1\n$ cat impossible\n10\n1 8 8 1\n0100000000\n0110000000\n0110000000\n0100000000\n0110000000\n0111111111\n0000000000\n0000000000\n0000001110\n0000000000\n$ ./zoomba < impossible\n0\n$ echo $?\n0\n$ cat input\n10\n1 8 8 1\n0000000000\n0110000000\n0110000000\n0100000000\n0110000000\n0111111100\n0000000000\n0000000000\n0000001110\n0000000000\n$ ./zoomba < input\nDDDDDDLLLLDLLL\n```\n\nΠαρατηρήστε ότι η λύση είναι διαφορετική απ' ό,τι εικονίζεται στο Σχήμα 2 αλλά παρόλα\nαυτά είναι σωστή και μία από τις βέλτιστες. Παρακάτω παραθέτουμε μερικά ακόμα\nπαραδείγματα. Φυσικά καλό είναι να δοκιμάσετε και εσείς το πρόγραμμά σας με διάφορα\nδωμάτια που είναι εντός προδιαγραφών ώστε να ελέγξετε την ορθότητα και την\nαποδοτικότητα της λύσης σας.\n\n```text\n$ cat maze\n10\n1 8 8 1\n1111111101\n0000000101\n0111110101\n0001000101\n1101011101\n0001010001\n0111010111\n0101010101\n0001010101\n0001000001\n$ ./zoomba < maze\nDDDDLLDDDDLLUUUUUURRUULLLLLLDDRRDDLLDDDR\n```\n\nΣτον φάκελο <https://github.com/progintro/data/tree/main/zoomba> μπορείτε να βρείτε και\nμεγαλύτερα παραδείγματα (τα μεγαλύτερα είναι συμπιεσμένα για λόγους χώρου, μπορείτε να\nτα αποσυμπιέσετε χρησιμοποιώντας την εντολή `tar`). Μερικές ενδεικτικές εκτελέσεις\nακολουθούν (έχουμε \"κόψει\" το output για λόγους χώρου):\n\n```text\n$ time ./zoomba < tricky1000\nUUUUUUU...UUUUUUUUULUURRRRR...RRRRRRRRRRRR\n\nreal    0m0.197s\nuser    0m0.145s\nsys     0m0.052s\n$ time ./zoomba < impossible1000\n0\n\nreal    0m0.155s\nuser    0m0.121s\nsys     0m0.034s\n\ntime ./zoomba < maze100\nDDDDLLL...DDLLDDD\n\nreal    0m0.003s\nuser    0m0.003s\nsys     0m0.000s\n$ ./zoomba < maze100 | wc -c\n2472\n$ ./zoomba < maze100 | md5sum -\n5b2b80b22c12408e82e10b2bbb625c48\n$ ./zoomba < guernica10000 | wc -c\n19173\n$ time ./zoomba < guernica10000 | md5sum -\n873bb6d49f1d6a6e36dc261cf3d79788  -\n\nreal    0m11.406s\nuser    0m10.233s\nsys     0m1.176s\n```\n\nΠροκειμένου να βελτιστοποιήσετε την λύση σας ίσως χρειαστεί (όχι αναγκαστικά!) να\nεμβαθύνετε σε θέματα αναζήτησης πέρα από αυτά που συζητήσαμε στο μάθημα - οι ενότητες\n2-4 της [Τεχνητής Νοημοσύνης της σχολής](https://cgi.di.uoa.gr/~ys02/siteAI2023/lectures.html)\nείναι ένα παράδειγμα από πηγές που μπορούν να σας βοηθήσουν σε αυτήν την κατεύθυνση.\n\nΣτο αρχείο `README.md` πρέπει να προσθέσετε οποιεσδήποτε παρατηρήσεις σας κατά την\nδιεκπεραίωση της άσκησης. Ο κώδικας απαιτείται να είναι καλά τεκμηριωμένος με σχόλια\nκαθώς αυτό θα είναι μέρος της βαθμολόγησης. Για τις υποβολές με την καλύτερη χρονική\nαπόδοση θα υπάρχει bonus βαθμολογία: η πρώτη υποβολή θα λάβει +100%, η δεύτερη +70% και\nη τρίτη +40%.",
  "hint": "Το δωμάτιο είναι ένας γράφος με κόμβους τα ελεύθερα κελιά και ακμές τις τέσσερις\nκινήσεις· η συντομότερη διαδρομή σε γράφο χωρίς βάρη βρίσκεται με αναζήτηση κατά\nπλάτος (BFS) με ουρά, αποθηκεύοντας για κάθε κελί από πού ήρθατε ώστε να ανακατασκευάσετε\nτη διαδρομή στο τέλος (ανάποδα). Για N = 10000 ο χάρτης έχει 10^8 κελιά: δεσμεύστε\nδυναμικά συμπαγείς πίνακες (π.χ. ένα byte ανά κελί) και αποφύγετε την αναδρομή, που θα\nγέμιζε τη στοίβα. Από το παράδειγμα του Σχήματος 2 βγάλτε ποια συντεταγμένη είναι η\nγραμμή και ποια η στήλη, και ελέγξτε προσεκτικά κάθε παράβαση της μορφής εισόδου."
 },
 {
  "id": "hw-2024-hw0-trolley",
  "kind": "homework",
  "title": "Το Πρόβλημα του Τρόλεϊ (trolley)",
  "source": {
   "title": "Εργασία 0 (2024-25), Άσκηση 3",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2024/hw0.pdf",
   "years": [
    2024
   ]
  },
  "chapters": [
   9,
   2,
   6
  ],
  "topics": [
   "input-output",
   "input-validation",
   "loops",
   "integer-representation"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α9.16",
  "path": "questions/homework/hw-2024-hw0-trolley.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2024-hw0-trolley.html",
  "statement": "**Το Πρόβλημα του Τρόλεϊ (trolley - 50 Μονάδες)**\n\nΤα αυτοκινούμενα οχήματα (self-driving cars) πρέπει κάποια στιγμή να λύσουν μια\nεκδοχή του *Προβλήματος του Τρόλεϊ*, του ηθικού διλήμματος που πρότεινε η Philippa\nFoot το 1967: το όχημα φτάνει σε μια διασταύρωση, τα φρένα δεν λειτουργούν, και πρέπει\nνα στρίψει αριστερά ή δεξιά, με κάθε επιλογή να έχει κάποιο κόστος.\n\nΓια τις ανάγκες αυτής της άσκησης, θα γράψετε ένα πρόγραμμα το οποίο λύνει\nεπαναλαμβανόμενες εκδοχές του προβλήματος του τρόλεϊ όπως θα χρειαζόταν να τις λύσει\nκαι ένας αυτόματος πιλότος σε ένα αυτοκινούμενο όχημα. Επειδή η άσκηση μας είναι\nκυρίως προγραμματιστική, δεν θα αποπειραθούμε να λύσουμε τα ηθικά διλήμματα και θα\nζητάμε από τον χρήστη να μας ενημερώσει για το κόστος της κάθε επιλογής μας αν πάμε\nαριστερά ή δεξιά.\n\n### Τεχνικές Προδιαγραφές\n\n- Repository Name: progintro/hw0-\\<YourUsername\\>\n- Αρχείο C (Filepath): trolley/src/trolley.c\n- Το αρχείο C που θα υποβληθεί πρέπει να μεταγλωττίζεται χωρίς ειδοποιήσεις για λάθη\n  και με κωδικό επιστροφής (exit code) που να είναι 0. Συγκεκριμένα, το αρχείο σας\n  **πρέπει** να μπορεί να μεταγλωττιστεί επιτυχώς με την ακόλουθη εντολή σε ένα από τα\n  μηχανήματα του εργαστηρίου (linuxXY.di.uoa.gr):\n  `gcc -O0 -m32 -Wall -Wextra -Werror -pedantic -o trolley trolley.c`\n- README Filepath: trolley/README.md\n- Το πρόγραμμά σας πρέπει να διαβάζει όλα τα κόστη που έδωσε ο χρήστης μέχρι το τέλος\n  αρχείου (End Of File - EOF).\n- Όλα τα κόστη που θα δοθούν στο πρόγραμμά σας θα είναι δεκαδικοί ακέραιοι στο εύρος:\n  $-10^{18}$ έως $10^{18}$.\n- Σε κάθε επανάληψη του προβλήματος το πρόγραμμά σας θα πρέπει να ζητάει από τον\n  χρήστη να δώσει τα κόστη για δύο επιλογές: αν πάει αριστερά (left) ή αν πάει δεξιά\n  (right). Το πρόγραμμά σας πρέπει να ζητάει το κόστος για την αριστερή επιλογή πρώτα\n  και στην συνέχεια για την δεξιά.\n- Τα κόστη που θα δώσει ο χρήστης μπορούν να διαχωρίζονται με κενό (space), tab ή νέα\n  γραμμή (new line).\n- Για κάθε δύο κόστη που δίνονται, το πρόγραμμά σας πρέπει να τυπώνει στην πρότυπη\n  έξοδο (stdout) είτε `Go left` είτε `Go right` - διαλέγοντας πάντα την επιλογή με το\n  μικρότερο κόστος. Αν οι δύο επιλογές έχουν το ίδιο κόστος, το πρόγραμμά σας πρέπει\n  να τυπώνει `Go left`.\n- Αν ο χρήστης δώσει EOF αντί για το πρώτο κόστος το πρόγραμμά σας πρέπει να\n  τερματίζει με κωδικό εξόδου (exit code) 0.\n- Αν δοθεί οποιαδήποτε είσοδος εκτός προδιαγραφών (για παράδειγμα ο χρήστης δίνει\n  μόνο το κόστος της αριστερής επιλογής) το πρόγραμμά σας πρέπει να τερματίζει με\n  κωδικό εξόδου (exit code) 1.\n- Για 10.000 επαναλήψεις του πειράματος, το πρόγραμμά σας πρέπει να ολοκληρώνει την\n  εκτέλεση μέσα σε: 1 δευτερόλεπτο.\n\nΠαρακάτω παραθέτουμε αλληλεπιδράσεις με μια ενδεικτική λύση:\n\n```text\nthanassis@linux14:~$ hostname\nlinux14\nthanassis@linux14:~$ gcc -O0 -m32 -Wall -Wextra -Werror -pedantic -o trolley trolley.c\nthanassis@linux14:~$ ./trolley\nPlease enter the cost of going left: 10\nPlease enter the cost of going right: 100\nGo left.\nPlease enter the cost of going left: 41\nPlease enter the cost of going right: 42\nGo left.\nPlease enter the cost of going left: 42\nPlease enter the cost of going right: 41\nGo right.\nPlease enter the cost of going left: 1000000\nPlease enter the cost of going right: 1000000\nGo left.\nPlease enter the cost of going left: Terminating.\nthanassis@linux14:~$ echo $?\n0\nthanassis@linux14:~$ ./trolley\nPlease enter the cost of going left: 42\nPlease enter the cost of going right: No right cost provided.\nthanassis@linux14:~$ echo $?\n1\nthanassis@linux14:~$ ./trolley\nPlease enter the cost of going left: 10000000000000\nPlease enter the cost of going right: 4\nGo right.\nPlease enter the cost of going left: -4\nPlease enter the cost of going right: -4\nGo left.\nPlease enter the cost of going left: 10000000000000\nPlease enter the cost of going right: 4000000000000\nGo right.\nPlease enter the cost of going left: Terminating.\nthanassis@linux14:~$ echo $?\n0\n```\n\nΣτο αρχείο README.md πρέπει να προσθέσετε οποιεσδήποτε παρατηρήσεις σας κατά την\nδιεκπεραίωση της άσκησης. Ο κώδικας απαιτείται να είναι καλά τεκμηριωμένος με σχόλια\nκαθώς αυτό θα είναι μέρος της βαθμολόγησης.",
  "hint": "Με `-m32` ο `long` έχει 32 bits, άρα για κόστη έως $10^{18}$ χρειάζεστε τύπο 64 bits\nκαι τον αντίστοιχο προσδιοριστή μορφής στη `scanf`. Η τιμή επιστροφής της `scanf`\nξεχωρίζει τις τρεις περιπτώσεις που σας ενδιαφέρουν: διαβάστηκε αριθμός, ήρθε EOF, ή\nήρθε κάτι που δεν είναι αριθμός. Προσέξτε ότι το EOF πριν από το αριστερό κόστος είναι\nκανονικός τερματισμός, ενώ πριν από το δεξί είναι σφάλμα.\n\n## Δείτε επίσης\n\n- [Υποδειγματική υποβολή φοιτητή](https://progintro.github.io/samples/code/trolley1/) (περιέχει λύση: δείτε την αφού λύσετε την άσκηση)\n- [Υποδειγματική υποβολή φοιτητή (2)](https://progintro.github.io/samples/code/trolley2/) (περιέχει λύση: δείτε την αφού λύσετε την άσκηση)"
 },
 {
  "id": "hw-2024-hw1-factor",
  "kind": "homework",
  "title": "Παραγοντοποίηση ημιπρώτων (factor)",
  "source": {
   "title": "Εργασία 1 (2024-25), Άσκηση 3 (Bonus)",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2024/hw1.pdf",
   "years": [
    2024
   ]
  },
  "chapters": [
   15,
   16,
   2
  ],
  "topics": [
   "math-algorithms",
   "complexity",
   "integer-representation",
   "command-line-args"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α15.17",
  "path": "questions/homework/hw-2024-hw1-factor.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2024-hw1-factor.html",
  "statement": "**Παραγοντοποίηση (factor - Bonus 50 Μονάδες)**\n\nΑυτή η άσκηση είναι Bonus, δηλαδή η λύση της *δεν* είναι απαραίτητη για να πάρει\nκάποιος/α όλες τις μονάδες της Εργασίας 1. Οι μονάδες από την όποια υποβολή για αυτήν\nτην άσκηση θα προστεθούν στον τελικό σας βαθμό του μαθήματος που περιλαμβάνει τις\nασκήσεις.\n\nΚάθε μη πρώτος (σύνθετος/composite) αριθμός μπορεί να γραφτεί σαν γινόμενο δύο ή\nπερισσότερων πρώτων αριθμών. Επομένως η παραγοντοποίηση (factorization) ενός φυσικού\nαριθμού n είναι το πρόβλημα της εύρεσης των πρώτων παραγόντων που το γινόμενό τους μας\nδίνει το n. Για παράδειγμα, η παραγοντοποίηση του αριθμού $42$ είναι\n$2\\cdot 3 \\cdot 7$. Συγκεκριμένα, σε αυτήν την άσκηση θα ασχοληθούμε με την\nπαραγοντοποίηση μιας συγκεκριμένης κατηγορίας σύνθετων αριθμών, τους ημιπρώτους\n(semiprimes).\n\n**Ορισμός 6**. Ένας φυσικός αριθμός λέγεται ημιπρώτος (semiprime), όταν είναι το\nγινόμενο ακριβώς δύο πρώτων αριθμών. Για παράδειγμα, ο αριθμός $46$ είναι semiprime\n($2\\cdot 23$) όπως και ο αριθμός $9$ ($3\\cdot 3$). Αντίθετα, ο αριθμός $42$ δεν είναι\nsemiprime.\n\nΤο πρόβλημα φαίνεται απλό, αλλά κανείς δεν έχει βρει μέχρι στιγμής αποδοτική λύση, και\nσε αυτό στηρίζεται η ασφάλεια του RSA. Σε αυτήν την άσκηση λοιπόν, καλείστε να γράψετε\nένα αποδοτικό πρόγραμμα το οποίο να παραγοντοποιεί ημιπρώτους (semiprimes).\n\n### Τεχνικές Προδιαγραφές\n\n- Repository Name: progintro/hw1-\\<YourUsername\\>\n- C Filepath: factor/src/factor.c\n- Το πρόγραμμά θα πρέπει να παίρνει ένα όρισμα από την γραμμή εντολών στην μορφή\n  `./factor semiprime`, με το πρώτο (`semiprime`) να είναι ο ημιπρώτος που θέλουμε να\n  παραγοντοποιήσουμε. Αν το πρόγραμμα εκτελεστεί με ορίσματα που δεν ακολουθούν τις\n  παραπάνω προδιαγραφές, πρέπει να εκτυπώσει αντίστοιχο μήνυμα όπως στα παρακάτω\n  παραδείγματα και να επιστρέφει με κωδικό εξόδου (exit code) 1.\n- Όλοι οι δεκαδικοί ακέραιοι που θα δοθούν στο πρόγραμμά σας θα είναι ημιπρώτοι και\n  στο εύρος: $[0, 2^{127}]$. Για οποιαδήποτε άλλη είσοδο, το πρόγραμμά σας πρέπει να\n  τερματίζει με κωδικό εξόδου 1.\n- Το αρχείο C που θα υποβληθεί πρέπει να μεταγλωττίζεται χωρίς ειδοποιήσεις για λάθη\n  και με κωδικό επιστροφής (exit code) που να είναι 0. Συγκεκριμένα, το αρχείο σας\n  **πρέπει** να μπορεί να μεταγλωττιστεί επιτυχώς με την ακόλουθη εντολή σε ένα από τα\n  μηχανήματα του εργαστηρίου (linuxXY.di.uoa.gr):\n  `gcc -O3 -Wall -Wextra -Werror -o factor factor.c -lm`\n- Μορφοποίηση: το αρχείο που θα υποβληθεί πρέπει να έχει μορφοποίηση σύμφωνη με το\n  C/C++ στυλ της Google. Για να μορφοποιήσετε το αρχείο σας, μπορείτε να τρέξετε την\n  ακόλουθη εντολή: `clang-format -i -style=Google factor.c` σε έναν υπολογιστή\n  εργαστηρίου. Μη μορφοποιημένα προγράμματα δεν θα εξεταστούν.\n- README Filepath: factor/README.md\n- **Ένα αρχείο που να περιέχει ένα στοιχείο εισόδου και ένα εξόδου \\*διαφορετικά\\*\n  από αυτά της εκφώνησης. Συγκεκριμένα προτείνουμε να βάλετε έναν συνδυασμό που\n  θεωρείται ότι είναι δύσκολος να γίνει σωστός κατά την υλοποίηση**.\n  - input Filepath: `factor/test/input.txt`\n  - output Filepath: `factor/test/output.txt`\n\n  Για παράδειγμα, το περιεχόμενο του input.txt αρχείου μπορεί να είναι: \"`93`\" και του\n  αντίστοιχου output.txt: \"`3 31`\". Προσοχή: αυτό το παράδειγμα δεν θα γίνει δεκτό από\n  την άσκηση επειδή αυτό το input-output ζευγάρι υπάρχει ήδη παρακάτω, επομένως πρέπει\n  να διαλέξετε κάποιο άλλο.\n- Πρέπει να ολοκληρώνει την εκτέλεση μέσα σε: 10 δευτερόλεπτα.\n- **Δεν επιτρέπεται χρήση προϋπολογισμένων αποτελεσμάτων**. Το πρόγραμμά σας πρέπει να\n  υπολογίζει το αποτέλεσμα χωρίς \"πρότερη γνώση\", δηλαδή χωρίς να έχετε ήδη\n  κωδικοποιήσει παραγοντοποιήσεις ημιπρώτων που έχετε βρει από προηγούμενους\n  υπολογισμούς σας μέσα στον κώδικα.\n- Καθώς αυτή η εργασία είναι Bonus, θα ελέγξουμε και ποιοτικά χαρακτηριστικά της\n  υποβολής. Μια ιδιαίτερα δυσνόητη ή μη διαχειρίσιμη λύση (π.χ., 6 nested if-else, 35\n  μεταβλητές στην ίδια συνάρτηση κτλ) θα οδηγήσει σε αφαίρεση μονάδων κατά την κρίση\n  του εξεταστή.\n\nΠαρακάτω παραθέτουμε την αλληλεπίδραση με μια ενδεικτική λύση:\n\n```text\n$ ./factor\nUsage: ./factor <semiprime>\n$ echo $?\n1\n$ ./factor 93\nFactors: 3 31\n$ echo $?\n0\n$ ./factor 9827348119\nFactors: 613 16031563\n$ # level: very hard\n$ ./factor 2524891914334062643\nFactors: 1175747593 2147477851\n$ # level: extremely hard\n$ ./factor 809724910412139638697047\nFactors: 783108713587 1033987869581\n$ # level: this is impossible\n$ ./factor 66162145239900452012870189875803961\nFactors: 206547667773749927 320323855277677343\n```\n\nΣτο αρχείο README.md πρέπει να προσθέσετε οποιεσδήποτε παρατηρήσεις κάνατε κατά την\nδιεκπεραίωση της άσκησης. Ο κώδικας απαιτείται να είναι καλά τεκμηριωμένος με σχόλια\nκαθώς αυτό θα είναι μέρος της βαθμολόγησης. Οι 10 γρηγορότερες λύσεις θα μοιραστούν\nένα bonus (extra) 500 μονάδων κατανεμημένων αναλογικά με τον παράγοντα $\\frac{1}{T}$\n(μέχρι το max: 200 μονάδες ανά υποβολή), όπου $T$ είναι ο συνολικός χρόνος που απαιτεί\nο αλγόριθμος της υλοποίησης για να παραγοντοποιήσει όλους τους ακεραίους που του\nδόθηκαν. Αν δούμε μια ιδιαίτερα ενδιαφέρουσα/αποδοτική λύση, θα ζητήσουμε μια\nπαρουσίαση από το παιδί που την υλοποίησε.",
  "hint": "Αριθμοί έως $2^{127}$ δεν χωρούν σε `long long`: χρειάζεστε ακέραιο 128 bits (π.χ. την\nεπέκταση `__int128` του gcc) και δική σας μετατροπή από/προς δεκαδικό string, αφού η\n`printf`/`strtoll` δεν τον υποστηρίζουν. Η δοκιμαστική διαίρεση έως $\\sqrt{n}$ αρκεί για\nτα πρώτα παραδείγματα αλλά όχι για τα «very hard» και πάνω· ψάξτε πιθανοτικούς\nαλγορίθμους όπως τον Pollard's rho σε συνδυασμό με έλεγχο πρώτων Miller-Rabin, και\nπροσέξτε την υπερχείλιση στον πολλαπλασιασμό modulo."
 },
 {
  "id": "hw-2024-hw1-gcd",
  "kind": "homework",
  "title": "Ο Αλγόριθμος του Ευκλείδη (gcd)",
  "source": {
   "title": "Εργασία 1 (2024-25), Άσκηση 1",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2024/hw1.pdf",
   "years": [
    2024
   ]
  },
  "chapters": [
   11,
   12
  ],
  "topics": [
   "recursion",
   "math-algorithms",
   "command-line-args",
   "input-validation"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α11.19",
  "path": "questions/homework/hw-2024-hw1-gcd.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2024-hw1-gcd.html",
  "statement": "**Ο Αλγόριθμος του Ευκλείδη (gcd - 50 Μονάδες)**\n\nΣτις προτάσεις 1-2 του 7ου τόμου των \"Στοιχείων\", ο Ευκλείδης περιγράφει έναν\nαλγόριθμο ο οποίος χρησιμοποιείται ακόμα και σήμερα και λέγεται προς τιμήν του\n*Αλγόριθμος του Ευκλείδη* (Euclidean Algorithm). Ο αλγόριθμος μας βοηθάει να λύσουμε\nτο πρόβλημα του *Μέγιστου Κοινού Διαιρέτη* (ΜΚΔ) ή *Greatest Common Divisor* (GCD)\nστα Αγγλικά: δοθέντων δύο αριθμών $a$ και $b$ ο μέγιστος κοινός διαιρέτης τους είναι ο\nμέγιστος αριθμός $d$ ο οποίος *διαιρεί* τους $a$ και $b$ χωρίς να αφήνει υπόλοιπο.\nΠιο επίσημα, έχουμε τους ορισμούς:\n\n**Ορισμός 1**. Αν ο $a$ και ο $b$ είναι ακέραιοι με $a\\neq 0$, λέμε ότι *ο $a$ διαιρεί\nτον $b$* αν υπάρχει ακέραιος $c$ έτσι ώστε $b = a \\cdot c$. Όταν ο $a$ διαιρεί τον $b$\nλέμε ότι ο $a$ είναι παράγοντας του $b$ και ότι ο $b$ είναι πολλαπλάσιο του $a$. Ο\nσυμβολισμός $a \\mid b$ σημαίνει ότι ο $a$ διαιρεί τον $b$ ($b\\bmod a = 0$). Αντίθετα\n$a \\nmid b$ συμβολίζει ότι ο $a$ δεν διαιρεί τον $b$ ($b\\bmod a \\neq 0$).\n\n**Ορισμός 2**. Έστω ότι οι $a$ και $b$ είναι ακέραιοι, όχι μηδενικοί και οι δύο. Ο\nμεγαλύτερος ακέραιος $d$ έτσι ώστε να είναι $d\\mid a$ και $d \\mid b$ ονομάζεται\n*μέγιστος κοινός διαιρέτης* των $a$ και $b$ και συμβολίζεται με $gcd(a, b)$.\n\nΓια να δούμε πως μπορούμε να λύσουμε ένα τέτοιο πρόβλημα. Έστω ότι οι δύο ακέραιοι\nείναι: το $42$ και το $18$. Στο Δημοτικό, προκειμένου βρούμε το ΜΚΔ\nπαραγοντοποιούσαμε τους δύο αριθμούς και ο ΜΚΔ ήταν το γινόμενο των κοινών\nπαραγόντων. Η παραγοντοποίηση του $18$ είναι: $2 \\cdot 3^2$ ενώ του $42$ είναι\n$2 \\cdot 3 \\cdot 7$ και επομένως οι $2\\cdot 3$ είναι κοινοί παράγοντες και\n$gcd(42, 18) = 6$.\n\nΗ παραγοντοποίηση δεν είναι κακή μέθοδος αλλά είναι γενικά δύσκολη. Ο αλγόριθμος του\nΕυκλείδη προτείνει κάτι σχετικά πιο εύκολο (να αναφέρουμε ότι ο αυθεντικός αλγόριθμος\nτου Ευκλείδη ήταν διαφορετικός, εδώ χρησιμοποιούμε μια πιο μοντέρνα εκδοχή του):\n\n$$\\text{gcd}(a, b) = \\begin{cases} b & \\text{if } a \\bmod b = 0 \\\\ \\text{gcd}(b, a \\bmod b) & \\text{otherwise} \\end{cases}$$\n\nΓια να \"τρέξουμε\" την αναδρομική εξίσωση για το παράδειγμά μας: $\\text{gcd}(42, 18)$.\nΈχουμε ότι $42\\bmod 18 = 6$ (διάφορο του 0) και επομένως παίρνουμε τον δεύτερο κλάδο\nτης συνάρτησης και υπολογίζουμε το $\\text{gcd}(18, 42 \\bmod 18) = \\text{gcd}(18, 6)$.\nΤώρα όμως έχουμε ότι $18 \\bmod 6 = 0$ και επομένως από τον πρώτο κλάδο της συνάρτησης\nέχουμε: $\\text{gcd}(18, 6) = 6$. Συνεπώς πήραμε και πάλι το αναμενόμενο αποτέλεσμα:\n$\\text{gcd}(42, 18) = 6$. Εύκολο; Θα δείξει!\n\nΓια το ζητούμενο αυτής της άσκησης λοιπόν, καλείστε να γράψετε ένα πρόγραμμα `gcd` που\nυπολογίζει αυτόματα και αποδοτικά τον μέγιστο κοινό διαιρέτη δύο ακεραίων αριθμών\nχρησιμοποιώντας τον αναδρομικό αλγόριθμο του Ευκλείδη.\n\n### Τεχνικές Προδιαγραφές\n\n- Repository Name: progintro/hw1-\\<YourUsername\\>\n- C Filepath: gcd/src/gcd.c\n- Το πρόγραμμά θα πρέπει να παίρνει δύο ακεραίους αριθμούς στο δεκαδικό σύστημα ως\n  ορίσματα από την γραμμή εντολών στην μορφή `./gcd num0 num1`. Αν το πρόγραμμα\n  εκτελεστεί με ορίσματα που δεν ακολουθούν τις παραπάνω προδιαγραφές, πρέπει να\n  εκτυπώσει αντίστοιχο μήνυμα όπως στα παρακάτω παραδείγματα και να επιστρέφει με\n  κωδικό εξόδου (exit code) 1.\n- Όλες οι παράμετροι θα είναι στο εύρος $[-10^{18}, 10^{18}]$. Σε περίπτωση που δοθεί\n  το μηδέν (0) το πρόγραμμά σας πρέπει να επιστρέφει με κωδικό εξόδου 1.\n- Το αρχείο C που θα υποβληθεί πρέπει να μεταγλωττίζεται χωρίς ειδοποιήσεις για λάθη\n  και με κωδικό επιστροφής (exit code) που να είναι 0. Συγκεκριμένα, το αρχείο σας\n  **πρέπει** να μπορεί να μεταγλωττιστεί επιτυχώς με την ακόλουθη εντολή σε ένα από τα\n  μηχανήματα του εργαστηρίου (linuxXY.di.uoa.gr):\n  `gcc -O3 -Wall -Wextra -Werror -pedantic -o gcd gcd.c`\n- README Filepath: gcd/README.md\n- **Ένα αρχείο που να περιέχει στοιχεία εισόδου και ένα εξόδου διαφορετικά από αυτά\n  της εκφώνησης. Συγκεκριμένα προτείνουμε να βάλετε έναν συνδυασμό που θεωρείται ότι\n  είναι δύσκολος να γίνει σωστός**.\n  - input Filepath: `gcd/test/input.txt`\n  - output Filepath: `gcd/test/output.txt`\n\n  Παράδειγμα που όμως δεν θα γίνει δεκτό από την άσκηση επειδή είναι ήδη στα\n  παραδείγματα παρακάτω, για το input.txt: \"`942 1042`\" και για το output.txt: \"`2`\".\n- Πρέπει να ολοκληρώνει την εκτέλεση μέσα σε: 1 δευτερόλεπτο.\n\nΠαρακάτω παραθέτουμε την αλληλεπίδραση με μια ενδεικτική λύση:\n\n```text\n$ hostname\nlinux14\n$ gcc -O3 -Wall -Wextra -Werror -pedantic -o gcd gcd.c\n$ ./gcd\nUsage: ./gcd <num1> <num2>\n$ echo $?\n1\n$ ./gcd 1\nUsage: ./gcd <num1> <num2>\n$ ./gcd 18 42\ngcd(18, 42) = 6\n$ ./gcd 42 18\ngcd(42, 18) = 6\n$ ./gcd -42 18\ngcd(-42, 18) = 6\n$ ./gcd 982451653 776531401\ngcd(982451653, 776531401) = 1\n$ ./gcd 78423360000000000 35241600000000000\ngcd(78423360000000000, 35241600000000000) = 960000000000\n$ ./gcd 68719476736 84767329979727872\ngcd(68719476736, 84767329979727872) = 68719476736\n$ echo $?\n0\n$ time ./gcd 1000000000000000000 999999999999999999\ngcd(1000000000000000000, 999999999999999999) = 1\n\nreal    0m0.009s\nuser    0m0.004s\nsys     0m0.004s\n```\n\nΣτο αρχείο README.md πρέπει να προσθέσετε οποιεσδήποτε παρατηρήσεις σας κατά την\nδιεκπεραίωση της άσκησης. Ο κώδικας απαιτείται να είναι καλά τεκμηριωμένος με σχόλια\nκαθώς αυτό θα είναι μέρος της βαθμολόγησης.",
  "hint": "Η αναδρομική συνάρτηση γράφεται σχεδόν αυτούσια από τον τύπο· η δυσκολία είναι γύρω\nτης. Μετατρέψτε τα ορίσματα με `strtoll` και ελέγξτε ότι όλο το string ήταν αριθμός,\nαπορρίψτε το μηδέν, και σκεφτείτε τι κάνει ο τελεστής `%` με αρνητικούς τελεστέους\nώστε το αποτέλεσμα να βγαίνει θετικό (δείτε το `gcd(-42, 18) = 6`). Στην έξοδο\nτυπώνονται τα ορίσματα όπως δόθηκαν."
 },
 {
  "id": "hw-2024-hw1-rsa",
  "kind": "homework",
  "title": "Ο Αλγόριθμος RSA (rsa)",
  "source": {
   "title": "Εργασία 1 (2024-25), Άσκηση 2",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2024/hw1.pdf",
   "years": [
    2024
   ]
  },
  "chapters": [
   11,
   8,
   12
  ],
  "topics": [
   "math-algorithms",
   "recursion",
   "integer-representation",
   "command-line-args",
   "input-validation"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α11.21",
  "path": "questions/homework/hw-2024-hw1-rsa.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2024-hw1-rsa.html",
  "statement": "**Ο Αλγόριθμος RSA (rsa - 50 Μονάδες)**\n\nΚάθε φορά που συνδεόμαστε σε μια υπηρεσία (ssh, webmail, instagram) τα bytes του\nκωδικού μας ταξιδεύουν στο δίκτυο, και η κρυπτογραφία φροντίζει να μην μπορεί να τα\nδιαβάσει οποιοσδήποτε. Σε αυτήν την άσκηση, θα ασχοληθούμε με έναν από τους πιο\nφημισμένους αλγορίθμους κρυπτογραφίας, τον αλγόριθμο RSA (Rivest-Shamir-Adleman,\n1977). Χρειαζόμαστε: (1) μια συνάρτηση *encrypt* που να \"κρύβει\" το μήνυμά μας ώστε\nνα μην μπορεί κάποιος άλλος να το διαβάσει καθώς το στέλνουμε και (2) μια συνάρτηση\n*decrypt* η οποία να παίρνει το κρυπτογραφημένο μήνυμά μας και να το μετατρέπει\n(αποκρυπτογραφεί) στο αρχικό.\n\nΠως όμως μπορούμε να \"κρύψουμε\" το μήνυμά μας; Η βασική ιδέα του RSA είναι η εξής:\nέστω ότι το μήνυμα που θέλουμε να στείλουμε είναι ένας ακέραιος $m$. Τότε για να\nκρύψουμε το μήνυμά μας αρκεί να το υψώσουμε σε μια μεγάλη δύναμη: $m^x$. Η\nαποκρυπτογράφηση μπορεί να γίνει εξίσου απλά, αρκεί να βρούμε έναν αριθμό $y$ έτσι\nώστε $\\left(m^x\\right)^y = m$. Βλέποντας αυτό το παράδειγμα, ίσως σκέφτεστε ότι $x = 2$\nκαι $y = \\frac{1}{2}$ είναι μια πιθανή λύση στο πρόβλημά μας. Η σκέψη σας είναι σωστή,\nαλλά επειδή οποιοσδήποτε μπορεί να υπολογίσει την τετραγωνική ρίζα ενός αριθμού δεν\nμπορούμε να χρησιμοποιήσουμε αυτές τις πράξεις και αριθμούς για ασφαλή κρυπτογράφηση.\nΓια να δούμε ποιους αριθμούς και πράξεις μπορούμε να χρησιμοποιήσουμε, χρειαζόμαστε\nπρώτα κάποιους ορισμούς:\n\n**Ορισμός 3**. Ένας φυσικός αριθμός p μεγαλύτερος του 1 ονομάζεται *πρώτος (prime)*\nόταν έχει σαν μόνους διαιρέτες (το υπόλοιπο της διαίρεσης είναι 0) το 1 και το p. Για\nπαράδειγμα, το 17 είναι πρώτος αριθμός, ενώ το 42 δεν είναι, αφού έχει σαν διαιρέτες\nτο 2, το 3 και το 7, εκτός από τους 1 και 42. Μπορείτε να επιβεβαιώσετε ότι οι πρώτοι\nαριθμοί που είναι μικρότεροι από το 100 είναι οι εξής:\n\n$$2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97$$\n\nΜαθηματικοί στο παρελθόν έχουν ασχοληθεί με πολλά γνωστά προβλήματα όπως η κατανομή\nτους. Μέχρι σήμερα, δεν έχει βρεθεί μια συνάρτηση που να παράγει τους πρώτους αριθμούς\nαποδοτικά.\n\n**Ορισμός 4**. Δύο ακέραιοι $a$ και $b$ είναι *πρώτοι μεταξύ τους ή σχετικά πρώτοι\n(coprime)* όταν ο μέγιστος κοινός διαιρέτης τους είναι το 1, δηλαδή\n$\\text{gcd}(a, b) = 1$. Για παράδειγμα, οι αριθμοί 8 και 9 είναι coprime εφόσον το\n$\\text{gcd}(8, 9) = 1$ παρόλο που κανείς από τους δυο τους δεν είναι ο ίδιος πρώτος.\n\n**Ορισμός 5**. Η συνάρτηση $\\phi : \\mathbb{N} \\rightarrow \\mathbb{N}$ του Euler (γνωστή\nκαι ως totient function) δέχεται έναν φυσικό αριθμό n και επιστρέφει το πλήθος των\nφυσικών αριθμών που είναι μικρότεροι του n και comprime με το n. Για παράδειγμα,\n$\\phi(9) = 6$, εφόσον υπάρχουν ακριβώς έξι coprime με το 9: 1, 2, 4, 5, 7 και 8. Η\nσυνάρτηση $\\phi$ έχει την πολλαπλασιαστική ιδιότητα, δηλαδή για κάθε δύο φυσικούς $a$,\n$b$ με $\\text{gcd}(a, b) = 1$ ισχύει ότι $\\phi(a\\cdot b) = \\phi(a)\\cdot \\phi(b)$.\nΕπίσης, αν ο αριθμός $a$ είναι πρώτος, τότε ισχύει πως $\\phi(a) = a - 1$. Για\nπαράδειγμα: $\\phi(5) = 4$, εφόσον οι αριθμοί 1, 2, 3, 4 είναι coprime ως προς το 5.\n\nΈχοντας τους παραπάνω ορισμούς, μπορούμε επιτέλους να ορίσουμε τους περιορισμούς για\nνα λειτουργήσει σωστά ο αλγόριθμος RSA:\n\n1. Έστω οι ακέραιοι $e$, $d$, $p$, $q$ (το μυστικό) και ο ακέραιος $m$ (το μήνυμα)\n2. Έστω ο ακέραιος $N = p \\cdot q$.\n3. Περιορισμός: όλοι οι ακέραιοι πρέπει να είναι θετικοί.\n4. Περιορισμός: το μήνυμα $m$ πρέπει να είναι μικρότερο του $N$.\n5. Περιορισμός: οι ακέραιοι $p$ και $q$ είναι πρώτοι.\n6. Περιορισμός: ο ακέραιος $e$ είναι coprime με το $\\phi(N)$.\n7. Περιορισμός: οι ακέραιοι $e$ και $d$ είναι αντίστροφοι, δηλαδή:\n   $e \\cdot d \\bmod \\phi(N) = 1$.\n\nΜε βάση τους παραπάνω περιορισμούς, μπορούμε πλέον να ορίσουμε την συνάρτηση\nκρυπτογράφησης encrypt ως:\n\n$$encrypt(m) = m^e \\bmod N$$\n\nΑντίστοιχα αν μας δώσουν έναν ακέραιο $c$ ($=m^e \\bmod N$) που είναι το\nκρυπτογραφημένο μήνυμα, μπορούμε να το αποκρυπτογραφήσουμε, χρησιμοποιώντας την\nσυνάρτηση decrypt:\n\n$$decrypt(c) = c^d \\bmod N$$\n\nΤο γιατί η παραπάνω πράξη μας δίνει το αρχικό μας μηνύμα είναι μεγάλη ιστορία\n($c^d \\bmod N = \\left(m^e\\right)^d\\bmod N = m^{e\\cdot d}\\bmod N = m^{1 + k\\phi(N)} \\bmod N = m \\bmod N$)\nαλλά μπορείτε να βρείτε όλα τα βήματα της απόδειξης στην\n[Wikipedia](https://en.wikipedia.org/wiki/Euler%27s_theorem).\n\nΦτάσαμε επιτέλους στο ζητούμενο αυτής της άσκησης: να γράψετε ένα πρόγραμμα το οποίο\nνα μπορεί να κρυπτογραφεί και να αποκρυπτογραφεί μηνύματα χρησιμοποιώντας τον παραπάνω\nαλγόριθμο RSA.\n\n### Τεχνικές Προδιαγραφές\n\n- Repository Name: progintro/hw1-\\<YourUsername\\>\n- C Filepath: rsa/src/rsa.c\n- Το πρόγραμμά θα πρέπει να παίρνει 5 ορίσματα από την γραμμή εντολών στην μορφή\n  `./rsa op e d p q`. Tο πρώτο `op` επιτρέπεται να είναι \"enc\" (για encryption) και\n  \"dec\" για decryption. Τα υπόλοιπα ορίσματα θα είναι ακέραιοι αριθμοί και θα είναι\n  στο εύρος $[-10^{18}, 10^{18}]$. Αν το πρόγραμμα εκτελεστεί με ορίσματα που δεν\n  ακολουθούν τις παραπάνω προδιαγραφές, πρέπει να εκτυπώσει αντίστοιχο μήνυμα όπως στα\n  παρακάτω παραδείγματα και να επιστρέφει με κωδικό εξόδου (exit code) 1.\n- Το πρόγραμμα θα πρέπει να διαβάζει το μήνυμα $m$ από την πρότυπη είσοδο (standard\n  input) ως έναν δεκαδικό αριθμό επίσης στο εύρος $[-10^{18}, 10^{18}]$. Γενικά, δεν\n  θα σας ζητηθεί να χρησιμοποιήσετε ακεραίους με περισσότερα από 64 bits.\n- Αν η είσοδος του χρήστη δεν πληροί τους περιορισμούς του αλγορίθμου RSA το πρόγραμμά\n  σας πρέπει να τερματίζει με κωδικό εξόδου 1 και αντίστοιχο μήνυμα λάθους όπως\n  δείχνουμε παρακάτω στις ενδεικτικές εκτελέσεις.\n- Το αρχείο C που θα υποβληθεί πρέπει να μεταγλωττίζεται χωρίς ειδοποιήσεις για λάθη\n  και με κωδικό επιστροφής (exit code) που να είναι 0. Συγκεκριμένα, το αρχείο σας\n  **πρέπει** να μπορεί να μεταγλωττιστεί επιτυχώς με την ακόλουθη εντολή σε ένα από τα\n  μηχανήματα του εργαστηρίου (linuxXY.di.uoa.gr):\n  `gcc -O3 -Wall -Wextra -Werror -pedantic -o rsa rsa.c`\n- README Filepath: rsa/README.md\n- Πρέπει να ολοκληρώνει την εκτέλεση μέσα σε: 1 δευτερόλεπτο.\n\nΠαρακάτω παραθέτουμε αλληλεπιδράσεις με μια ενδεικτική λύση. Ας δοκιμάσουμε να\nστείλουμε το μήνυμα \"42\" ($m = 42$) χρησιμοποιώντας το μυστικό \"257 257 173 193\"\n($e = 257$, $d = 257$, $p = 173$, $q = 193$):\n\n```text\n$ echo 42 | ./rsa enc 257 257 173 193\n6990\n$ echo $?\n0\n```\n\nΆρα το κρυπτογραφημένο μήνυμα που μπορούμε να στείλουμε είναι ο αριθμός $c = 6990$.\nΕίναι σωστός; Πρέπει να κάνουμε την πράξη $42^{257}\\bmod (173 \\cdot 193)$ το οποίο\nόντως αν χρησιμοποιήσουμε ένα [online calculator](https://rsa-calculator.netlify.app/)\nφαίνεται σωστό (αντίστοιχα μπορείτε να κάνετε πειράματα με τους δικούς σας\nσυνδυασμούς αριθμών). Για να δούμε αν μπορούμε να αποκρυπτογραφήσουμε το αρχικό μας\nμήνυμα:\n\n```text\n$ echo 6990 | ./rsa dec 257 257 173 193\n42\n$ echo $?\n0\n```\n\nΠήραμε όντως πίσω το αρχικό μας μήνυμα! Παρακάτω δοκιμάζουμε να κρυπτογραφήσουμε και\nνα αποκρυπτογραφήσουμε διάφορους συνδυασμούς που καλύπτουν τις προδιαγραφές παραπάνω:\n\n```text\n$ ./rsa\nUsage: ./rsa enc|dec <exp_exp> <priv_exp> <prime1> <prime2>\n$ echo $?\n1\n$ ./rsa pop 1 2 3 4\nFirst argument must be 'enc' or 'dec'\n$ echo $?\n1\n$ ./rsa enc 1 2 -3 4\nNegative numbers are not allowed\n$ echo $?\n1\n$ ./rsa enc 1 2 3 4\np and q must be prime\n$ echo $?\n1\n$ ./rsa enc 3 6 17 19\ne is not coprime with phi(N)\n$ echo $?\n1\n$ ./rsa enc 5 6 17 19\ne * d mod phi(N) is not 1\n$ echo $?\n1\n$ echo 500 | ./rsa enc 5 173 17 19\nMessage is larger than N\n$ echo $?\n1\n$ echo -42 | ./rsa enc 5 173 17 19\nNegative numbers are not allowed\n$ echo $?\n1\n$ echo 42 | ./rsa enc 5 173 17 19\n264\n$ echo 42 | ./rsa enc 17 26153 131 229\n27187\n$ echo 27187 | ./rsa dec 257 257 173 193\n5343\n$ echo 27187 | ./rsa dec 17 26153 131 229\n42\n$ echo 117 | ./rsa enc 17 26153 131 229 | ./rsa dec 17 26153 131 229\n117\n$ echo 43434343 | ./rsa enc 65537 2278459553 62971 38609 |\n  ./rsa dec 65537 2278459553 62971 38609\n43434343\n$ echo 42 | ./rsa enc 65537 2278459553 62971 38609 > enc_msg\n$ cat enc_msg\n741088023\n$ time ./rsa dec 65537 2278459553 62971 38609 < enc_msg\n42\n\nreal    0m0.011s\nuser    0m0.004s\nsys     0m0.008s\n```\n\nΚαθώς οι εκθέτες του μυστικού στον οποίο υψώνουμε το μήνυμα γίνονται μεγαλύτεροι,\nείναι πιθανό πως το πρόγραμμά σας θα αρχίσει να παίρνει όλο και περισσότερο χρόνο για\nνα τερματίσει. Αν παρατηρήσετε πως κάτι τέτοιο συμβαίνει και στον δικό σας αλγόριθμο,\nμπορείτε να δοκιμάσετε βελτιωμένους αλγόριθμους υπολογισμού της δύναμης ενός ακεραίου\n([Repeated Squaring](https://en.wikipedia.org/wiki/Exponentiation_by_squaring),\n[Modular Exponentiation](https://en.wikipedia.org/wiki/Modular_exponentiation)).\n\nΣτο αρχείο README.md πρέπει να προσθέσετε οποιεσδήποτε παρατηρήσεις σας κατά την\nδιεκπεραίωση της άσκησης. Ο κώδικας απαιτείται να είναι καλά τεκμηριωμένος με σχόλια\nκαθώς αυτό θα είναι μέρος της βαθμολόγησης.",
  "hint": "Μην υπολογίσετε ποτέ ολόκληρο το $m^e$: παίρνετε το υπόλοιπο mod $N$ μετά από κάθε\nπολλαπλασιασμό και, για μεγάλους εκθέτες, χρησιμοποιείτε ύψωση σε δύναμη με\nεπαναλαμβανόμενο τετραγωνισμό (λογαριθμικά βήματα). Προσοχή στην υπερχείλιση: το\nγινόμενο δύο υπολοίπων κοντά στο $N$ μπορεί να μη χωρά σε 64 bits. Κάντε τους ελέγχους\nμε τη σειρά που δείχνουν τα παραδείγματα (ορίσματα, αρνητικοί, πρώτοι, coprime,\nαντίστροφοι, μέγεθος μηνύματος) και επαναχρησιμοποιήστε τον ΜΚΔ της άσκησης gcd."
 },
 {
  "id": "hw-2024-hw2-future",
  "kind": "homework",
  "title": "Προβλέποντας το Μέλλον (future)",
  "source": {
   "title": "Εργασία 2 (2024-25), Άσκηση 1",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2024/hw2.pdf",
   "years": [
    2024
   ]
  },
  "chapters": [
   18,
   13,
   12
  ],
  "topics": [
   "files",
   "dynamic-memory",
   "command-line-args",
   "floating-point",
   "arrays"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α18.11",
  "path": "questions/homework/hw-2024-hw2-future.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2024-hw2-future.html",
  "statement": "**Προβλέποντας το Μέλλον (future - 50 Μονάδες)**\n\nΌλες οι προβλέψεις, από τον καιρό μέχρι την επόμενη λέξη σε μια πρόταση, αξιολογούνται\nμε ένα κοινό κριτήριο: το πόσο ακριβείς είναι. Σε αυτήν την άσκηση, θα υλοποιήσουμε\nέναν αλγόριθμο που χρησιμοποιείται κατεξοχήν για να κάνουμε προβλέψεις, τον *κινούμενο\nμέσο όρο (Simple Moving Average - SMA)*. Ο κινούμενος μέσος όρος είναι παρεμφερής με\nτον κανονικό μέσο όρο, με μια διαφορά: ο κινούμενος μέσος όρος απαιτεί και ένα\n\"παράθυρο\" (window), δηλαδή τον αριθμό των τιμών (μετρώντας από το τέλος) που θέλουμε\nνα λάβουμε υπόψη μας στον υπολογισμό του μέσου όρου. Για παράδειγμα, ας υποθέσουμε ότι\nέχουμε αυτές τις 10 τιμές:\n\n```text\n9  7  7  1  4  4  4  38  8  4\n```\n\nΟ μέσος όρος αυτών των τιμών είναι\n$\\frac{9 + 7 + 7 + 1 + 4 + 4 + 4 + 38 + 8 + 4}{10} = 8.60$. Για να υπολογίσουμε τον\nκινούμενο μέσο, πρέπει να επιλέξουμε ένα παράθυρο, έστω 3. Τότε ο κινούμενος μέσος με\nπαράθυρο 3 για αυτά τα στοιχεία λαμβάνει υπόψη του μόνο τα τελευταία 3:\n\n$$9 \\quad 7 \\quad 7 \\quad 1 \\quad 4 \\quad 4 \\quad 4 \\quad \\underbrace{38 \\quad 8 \\quad 4}_{SMA_3}$$\n\nκαι επομένως $SMA_3 = \\frac{38 + 8 + 4}{3} = 16.67$. Αντίστοιχα, μπορούν να οριστούν\nκινούμενοι μέσοι με μικρότερα παράθυρα (π.χ., παράθυρο 1 σημαίνει μόνο το τελευταίο\nστοιχείο) ή μεγαλύτερα παράθυρα (π.χ., παράθυρο 10 θα λάμβανε υπόψη του όλες τις τιμές\nπαραπάνω).\n\nΣε αυτήν την άσκηση λοιπόν, καλείστε να υλοποιήσετε ένα πρόγραμμα το οποίο θα\nυπολογίζει τον κινούμενο μέσο όρο για μια σειρά από δεδομένα και να τον εκτυπώνει ως\nπρόβλεψη.\n\n### Τεχνικές Προδιαγραφές\n\n- Repository Name: progintro/hw2-\\<YourUsername\\>\n- C Filepath: future/src/future.c\n- Το πρόγραμμά θα πρέπει να παίρνει ως κυρίως όρισμα το όνομα του αρχείου που περιέχει\n  τα δεδομένα μας. Προαιρετικά, μπορεί να παίρνει και άλλα δύο ορίσματα προκειμένου να\n  ορίσουμε το μέγεθος του \"παραθύρου\" που θέλουμε για τον κινούμενο μέσο όρο. Για\n  παράδειγμα αν το τρέξουμε ως `./future data.txt --window 42`, σημαίνει υπολόγισε τον\n  κινούμενο μέσο όρο με παράθυρο 42 για τα δεδομένα του αρχείου data.txt. Αν δεν δοθεί\n  παράμετρος για το μέγεθος του παραθύρου, τότε το (default) παράθυρο πρέπει να είναι\n  μεγέθους 50. Αν το πρόγραμμα εκτελεστεί με ορίσματα που δεν ακολουθούν τις παραπάνω\n  προδιαγραφές, πρέπει να εκτυπώσει αντίστοιχο μήνυμα όπως στα παρακάτω παραδείγματα\n  και να επιστρέφει με κωδικό εξόδου (exit code) 1.\n- Το αρχείο με τα δεδομένα θα περιέχει αριθμούς κινητής υποδιαστολής με μέχρι δύο\n  ψηφία ακριβείας. Γενικά, δεν θα σας ζητηθεί να χρησιμοποιήσετε μεγαλύτερη ακρίβεια\n  από double.\n- Αν το παράθυρο είναι μικρότερο από 1 ή μεγαλύτερο από τον συνολικό αριθμό δεδομένων,\n  το πρόγραμμά σας πρέπει να τερματίζει με μήνυμα σφάλματος όπως στα παραδείγματα. Το\n  μήνυμά σας πρέπει να τυπώνεται στο stderr του προγράμματος. Το μέγεθος του παραθύρου\n  δεν θα υπερβεί το $10^{18}$.\n- Το αρχείο C που θα υποβληθεί πρέπει να μεταγλωττίζεται χωρίς ειδοποιήσεις για λάθη\n  και με κωδικό επιστροφής (exit code) που να είναι 0. Συγκεκριμένα, το αρχείο σας\n  **πρέπει** να μπορεί να μεταγλωττιστεί επιτυχώς με την ακόλουθη εντολή σε ένα από τα\n  μηχανήματα του εργαστηρίου (linuxXY.di.uoa.gr):\n  `gcc -Os -Wall -Wextra -Werror -pedantic -o future future.c`\n- README Filepath: future/README.md\n- Πρέπει να ολοκληρώνει την εκτέλεση μέσα σε: 1 δευτερόλεπτο.\n\nΠαραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ ./future\nUsage: ./future <filename> [--window N (default: 50)]\n$ cat values.txt\n9 7 7 1 4 4 4 38 8 4\n$ ./future values.txt --window 10\n8.60\n$ echo $?\n0\n$ ./future values.txt --window 3\n16.67\n$ ./future values.txt --window 1\n4.00\n$ ./future values.txt --window 0\nWindow too small!\n$ echo $?\n1\n$ ./future values.txt --window 0 2> out\n$ cat out\nWindow too small!\n$ ./future values.txt --window 12\nWindow too large!\n$ echo $?\n1\n$ ./future values.txt --window 1000000000000\nFailed to allocate window memory\n```\n\nΦυσικά οι ίδιοι έλεγχοι μπορούν να γίνουν με πραγματικά δεδομένα και να δείτε αν οι\nπροβλέψεις του προγράμματός μας είναι καλές (Το αρχείο dow_jones.txt βρίσκεται στο\n<https://github.com/progintro/data>):\n\n```text\n$ ./future dow_jones.txt\n43471.71\n$ ./future dow_jones.txt --window 200\n40677.19\n$ ./future dow_jones.txt --window 1000\n35273.61\n$ wc -l dow_jones.txt\n8302 dow_jones.txt\n$ ./future dow_jones.txt --window 8000\n15447.33\n```\n\nΣτο αρχείο README.md πρέπει να προσθέσετε οποιεσδήποτε παρατηρήσεις σας κατά την\nδιεκπεραίωση της άσκησης. Ο κώδικας απαιτείται να είναι καλά τεκμηριωμένος με σχόλια\nκαθώς αυτό θα είναι μέρος της βαθμολόγησης.\n\n### Bonus (Προαιρετικό)\n\nΠιστεύετε πως μπορείτε να φτιάξετε αλγορίθμους που προβλέπουν πως θα κινηθεί ένα\nοικονομικό asset καλύτερα από τον κινούμενο μέσο; Αν ναι, προσθέστε ένα easter egg\noption στο πρόγραμμά σας ονόματι `--compete` και θα μπείτε αυτόματα στον διαγωνισμό\nμας. Η αξιολόγηση θα γίνει με πραγματικά δεδομένα από χρηματιστήρια του κόσμου. Η\nδιεπαφή θα είναι παρόμοια με παραπάνω, απλά υπολογίζετε την καλύτερή σας πρόβλεψη για\nτην επόμενη τιμή σε μια σειρά δεδομένων:\n\n```text\n$ ./future dow_jones.txt --compete\n43455.32\n```\n\nΟι τρεις καλύτερες υποβολές θα λάβουν 100%, 70% και 40% έξτρα βαθμολογία σε αυτήν την\nάσκηση.",
  "hint": "Χρειάζεστε μόνο τις τελευταίες $N$ τιμές: ένας κυκλικός πίνακας (ring buffer) μεγέθους\nίσου με το παράθυρο, δεσμευμένος με `malloc`, κρατά αυτές τις τιμές όσο διαβάζετε το\nαρχείο, χωρίς να ξέρετε από πριν πόσες είναι. Ελέγξτε την τιμή επιστροφής της `malloc`\n(δείτε το παράθυρο $10^{12}$) και της `fopen`, διαβάστε το παράθυρο ως 64-bit ακέραιο,\nκαι θυμηθείτε ότι τα μηνύματα λάθους πάνε στο `stderr`."
 },
 {
  "id": "hw-2024-hw2-jabbamaps",
  "kind": "homework",
  "title": "Το Καλύτερο GPS (jabbamaps)",
  "source": {
   "title": "Εργασία 2 (2024-25), Άσκηση 2",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2024/hw2.pdf",
   "years": [
    2024
   ]
  },
  "chapters": [
   25,
   18,
   14
  ],
  "topics": [
   "graphs",
   "dynamic-programming",
   "complexity",
   "strings",
   "files",
   "multidim-arrays"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α25.3",
  "path": "questions/homework/hw-2024-hw2-jabbamaps.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2024-hw2-jabbamaps.html",
  "statement": "**Το Καλύτερο GPS (jabbamaps - 50 Μονάδες)**\n\nΠολλές εφαρμογές (όπως το Google Maps) σου επιτρέπουν να προσθέσεις πολλές στάσεις στη\nδιαδρομή σου, αλλά δεν σου προτείνουν να τις αναδιατάξεις ακόμη και αν αυτό σου\nγλύτωνε χρόνο. Έχει σημασία με ποια σειρά θα καλύψουμε αυτές τις στάσεις; Αυτό θα\nείναι το πρόβλημα με το οποίο θα ασχοληθούμε σε αυτήν την άσκηση.\n\nΑς δούμε μια απλοποιημένη εκδοχή του προβλήματός μας για 4 στάσεις. Έστω ότι θέλουμε\nνα κάνουμε τον γύρο τις Ελλάδας και συγκεκριμένα να καλύψουμε τέσσερις πόλεις: Αθήνα,\nΘεσσαλονίκη, Γιάννενα και Πάτρα. Από κάθε πόλη μπορούμε να κινηθούμε προς οποιαδήποτε\nάλλη, αλλά κάθε κίνησή μας έχει ένα κόστος (έστω χιλιομετρικό). Για παράδειγμα, για να\nπάμε από την Αθήνα στην Θεσσαλονίκη έχουμε κόστος 501, ενώ για να πάμε στην Πάτρα\nέχουμε κόστος 224. Θεωρούμε ότι η κατεύθυνση δεν έχει σημασία και το χιλιομετρικό\nκόστος είναι το ίδιο ανεξαρτήτως κατεύθυνσης.\n\n```mermaid\nflowchart LR\n    A[\"Αθήνα\"] ---|501| T[\"Θεσσαλονίκη\"]\n    A ---|422| I[\"Ιωάννινα\"]\n    A ---|224| P[\"Πάτρα\"]\n    P ---|468| T\n    P ---|223| I\n    T ---|261| I\n```\n\n*Σχήμα: Από κάθε πόλη μπορείς να αποφασίσεις να κινηθείς σε οποιαδήποτε άλλη πόλη με κάποιο χιλιομετρικό κόστος. Ποια είναι η πιο αποδοτική (από απόψεως κόστους) σειρά με την οποία μπορείς να τις επισκεφτείς;*\n\nΈστω ότι ξεκινάμε από την Αθήνα (η πόλη από την οποία ξεκινάμε δεν έχει σημασία, καθώς\nπρέπει να επισκεφτούμε όλες τις πόλεις), έχουμε 3 διαφορετικές επιλογές για την πόλη\nπου θα επισκεφτούμε στην συνέχεια. Προσέξτε ότι οποιαδήποτε πόλη επιλέξουμε έχει\nσυνέπειες και για τις επόμενες επιλογές μας. Ποιο είναι το μονοπάτι με το ελάχιστο\nκόστος; Αν επιλέξω να κάνω το Αθήνα → Θεσσαλονίκη → Ιωάννινα → Πάτρα θα χρειαστώ\n501 + 261 + 223 = 985 χιλιόμετρα. Αντίθετα, αν πάω Αθήνα → Πάτρα → Ιωάννινα →\nΘεσσαλονίκη χρειάζομαι 224 + 223 + 261 = 708 χιλιόμετρα. Με μια αλλαγή στην σειρά\nεπίσκεψης γλύτωσα 277 χιλιόμετρα! Είναι όμως αυτή η βέλτιστη επιλογή; Πόσες δυνατές\nδιαφορετικές διατάξεις υπάρχουν στην σειρά με την οποία μπορώ να επισκεφτώ τις πόλεις;\n\nΤο πρόβλημα στο οποίο πρέπει να αποφασίσουμε με ποια σειρά θα επισκεφτούμε μια σειρά\nπόλεων λέγεται *Travelling Salesman Problem*, ελληνιστί το πρόβλημα του πλανόδιου\nπωλητή. Φτάσαμε επομένως στο ζητούμενο αυτής της άσκησης: να γράψετε ένα πρόγραμμα το\nοποίο θα διαβάζει έναν χάρτη με τις αποστάσεις όλων των ζευγών πόλεων που θέλουμε να\nεπισκεφτούμε και θα μας υπολογίζει το μονοπάτι ελαχίστου κόστους, εύκολα, γρήγορα και\nπάνω απ’όλα τζάμπα!\n\n### Τεχνικές Προδιαγραφές\n\n- Repository Name: progintro/hw2-\\<YourUsername\\>\n- C Filepath: jabbamaps/src/jabbamaps.c\n- Το πρόγραμμά θα πρέπει να παίρνει ακριβώς ένα όρισμα, το όνομα του αρχείου που\n  περιέχει τα δεδομένα του χάρτη. Αν το πρόγραμμα εκτελεστεί με ορίσματα που δεν\n  ακολουθούν τις παραπάνω προδιαγραφές, πρέπει να εκτυπώσει αντίστοιχο μήνυμα όπως στα\n  παρακάτω παραδείγματα και να επιστρέφει με κωδικό εξόδου (exit code) 1.\n- Το αρχείο με τα δεδομένα του χάρτη θα έχει σε κάθε γραμμή του ένα ζεύγος πόλεων και\n  στην συνέχεια την απόστασή τους. Συγκεκριμένα, κάθε γραμμή θα είναι της μορφής\n  `city1-city2: distance`, όπου city1 και city2 είναι το ζεύγος των πόλεων και\n  distance είναι η απόστασή τους. Τα ονόματα των πόλεων δεν θα έχουν τους χαρακτήρες\n  ’-’ ή ’:’ και η απόστασή τους θα είναι πάντα ένας ακέραιος αριθμός.\n- Η πρώτη πόλη που θα διαβάσουμε στον χάρτη θέλουμε να είναι η πόλη από την οποία θα\n  ξεκινήσουμε την διαδρομή μας. Το συνολικό κόστος δεν θα πρέπει να περιλαμβάνει το\n  κόστος επιστροφής στην αρχική μας πόλη.\n- Οι αποστάσεις των πόλεων δεν θα υπερβαίνουν το $2^{31}$.\n- Οι πόλεις που θα πρέπει να επισκεφτούμε δεν θα είναι πάνω από 64.\n- Το μόνοπάτι σας πρέπει να επισκεφτεί *κάθε* πόλη *ακριβώς* μία φορά.\n- Το αρχείο C που θα υποβληθεί πρέπει να μεταγλωττίζεται χωρίς ειδοποιήσεις για λάθη\n  και με κωδικό επιστροφής (exit code) που να είναι 0. Συγκεκριμένα, το αρχείο σας\n  **πρέπει** να μπορεί να μεταγλωττιστεί επιτυχώς με την ακόλουθη εντολή σε ένα από τα\n  μηχανήματα του εργαστηρίου (linuxXY.di.uoa.gr):\n  `gcc -m32 -Ofast -Wall -Wextra -Werror -pedantic -o jabbamaps jabbamaps.c`\n- README Filepath: jabbamaps/README.md\n- Πρέπει να ολοκληρώνει την εκτέλεση μέσα σε: 30 δευτερόλεπτα.\n\nΕνδεικτικές εκτελέσεις ακολουθούν σε κάποιους από τους χάρτες που υπάρχουν στο\n<https://github.com/progintro/data>:\n\n```text\n$ cat map4.txt\nAthens-Thessaloniki: 501\nAthens-Ioannina: 422\nAthens-Patras: 224\nPatras-Thessaloniki: 468\nPatras-Ioannina: 223\nThessaloniki-Ioannina: 261\n$ ./jabbamaps map4.txt\nWe will visit the cities in the following order:\nAthens -(224)-> Patras -(223)-> Ioannina -(261)-> Thessaloniki\nTotal cost: 708\n$ ./jabbamaps map7.txt\nWe will visit the cities in the following order:\nAthens -(211)-> Amfissa -(122)-> Patras -(223)-> Ioannina -(128)->\n  Trikala -(123)-> Volos -(211)-> Thessaloniki\nTotal cost: 1018\n```\n\nΙδανικά, επιθυμούμε το πρόγραμμά μας να δουλεύει και για μεγαλύτερους χάρτες, όσο\nασυνήθιστα και να είναι τα ονόματα των πόλεων ή οι αποστάσεις μεταξύ τους. Για\nπαράδειγμα:\n\n```text\n$ ./jabbamaps tatooine.txt\nWe will visit the cities in the following order:\nRepublic City -(65)-> Aldera -(124)-> Anchorhead -(44)-> Lessu -(45)->\n  Mos Pelgo -(32)-> Canto Bight -(65)-> Mos Espa -(80)-> Coronet City -(53)->\n  Hanna City -(50)-> Sern Prime -(62)-> NiJedha -(20)-> Kachirho -(66)->\n  Tipoca City -(141)-> Sundari -(51)-> Galactic City -(29)->\n  Capital City (Lothal City) -(157)-> Mos Eisley -(317)-> Stalgasin Hive -(26)->\n  Coral City -(25)-> Otoh Gunga -(13)-> Theed -(18)-> Cloud City -(136)-> Eriadu City\nTotal cost: 1619\n```\n\nΌσο περισσότερες οι πόλεις, τόσοι περισσότεροι οι συνδυασμοί που πρέπει να εξετάσουμε\nκαι το πρόβλημα πλέον δεν είναι εύκολο να επιβεβαιωθεί \"με το μάτι\". Είναι η λύση που\nβρήκαμε η βέλτιστη ή μήπως υπάρχει καλύτερη;\n\nΩς συνήθως, υπενθυμίζουμε πως στο αρχείο README.md πρέπει να προσθέσετε οποιεσδήποτε\nπαρατηρήσεις σας κατά την διεκπεραίωση της άσκησης. Ο κώδικας απαιτείται να είναι καλά\nτεκμηριωμένος με σχόλια καθώς αυτό θα είναι μέρος της βαθμολόγησης.",
  "hint": "Πρώτα μετατρέψτε το αρχείο σε πίνακα αποστάσεων: κάθε νέο όνομα πόλης παίρνει έναν\nαριθμό (προσοχή, τα ονόματα έχουν κενά και παρενθέσεις), και η απόσταση μπαίνει στο\n`dist[i][j]` και στο `dist[j][i]`. Η δοκιμή όλων των $(n-1)!$ διατάξεων σβήνει ήδη\nγύρω στις 12 πόλεις· για περισσότερες σκεφτείτε δυναμικό προγραμματισμό πάνω σε\nυποσύνολα (bitmask, αλγόριθμος Held-Karp), που όμως για 64 πόλεις δεν χωρά ούτε σε\nμνήμη ούτε σε χρόνο, οπότε εκεί χρειάζεστε ευριστικές μεθόδους (nearest neighbour,\n2-opt). Με `-m32`, κρατήστε το συνολικό κόστος σε τύπο 64 bits."
 },
 {
  "id": "hw-2024-hw2-jason",
  "kind": "homework",
  "title": "Το Δικό σου Chatbot (jason)",
  "source": {
   "title": "Εργασία 2 (2024-25), Άσκηση 3",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2024/hw2.pdf",
   "years": [
    2024
   ]
  },
  "chapters": [
   14,
   11,
   18
  ],
  "topics": [
   "strings",
   "dynamic-memory",
   "files",
   "recursion",
   "code-organization",
   "input-output"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α14.10",
  "path": "questions/homework/hw-2024-hw2-jason.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2024-hw2-jason.html",
  "statement": "**Το Δικό σου Chatbot - (jason - 50 Μονάδες)**\n\nΗ τεχνητή νοημοσύνη έχει μπει για τα καλά στην ζωή μας, και χρήστες και\nπρογραμματιστές/τριες βρίσκουν συνεχώς νέες εφαρμογές της. Πόσο δύσκολο είναι όμως να\nφτιάξουμε ένα εργαλείο που να μπορεί να αξιοποιήσει τις υπηρεσίες τεχνητής νοημοσύνης\nκαι να προσφέρει λύσεις σε χρήστες; Αυτή είναι η ερώτηση που θα μας απασχολήσει σε\nαυτήν την άσκηση.\n\nΠροκειμένου να μιλήσουμε με απομακρυσμένες υπηρεσίες, πρέπει να μπορούμε να μιλήσουμε\nτην γλώσσα τους. Τυχαίνει σήμερα πάμπολλες εφαρμογές στο internet να μεταφέρουν\nδεδομένα χρησιμοποιώντας μια μορφοποίηση (data format) που λέγεται JSON (JavaScript\nObject Notation). Για να δούμε ένα παράδειγμα. Έστω ότι έχουμε ένα αρχείο\n`person.json` με τα ακόλουθα περιεχόμενα:\n\n```text\n{\n  \"first_name\": \"John\",\n  \"last_name\": \"Smith\",\n  \"age\": 27,\n  \"address\": {\n    \"street_address\": \"21 2nd Street\",\n    \"city\": \"New York\",\n    \"state\": \"NY\",\n  },\n  \"phone_numbers\": [\n    {\n      \"type\": \"home\",\n      \"number\": \"212 555-1234\"\n    },\n    {\n      \"type\": \"office\",\n      \"number\": \"646 555-4567\"\n    }\n  ],\n  \"children\": [\n    \"Catherine\",\n    \"Thomas\",\n    \"Trevor\"\n  ],\n  \"spouse\": null\n}\n```\n\nΤο παραπάνω παράδειγμα JSON παρουσιάζει ιεραρχικά τα δεδομένα για ένα άτομο.\nΠαρατηρούμε ότι όλα τα δεδομένα είναι μέσα σε ένα object (περικλείονται από αγκύλες {\nκαι }) και μέσα σε αυτό έχει διάφορα πεδία που κλείνονται μέσα σε διπλά quotes \":\nfirst_name, last_name, ..., children, spouse. Πέρα από αυτό παρατηρούμε ότι κάθε πεδίο\nμπορεί να έχει ως τιμή (ότι ακολουθεί την άνω και κάτω τελεία \":\") ένα από τα\nακόλουθα:\n\n1. έναν αριθμό (π.χ., `\"age\": 27`)\n2. ένα string (`\"first_name\": \"John\"`)\n3. μια λίστα από δεδομένα (`\"children\": [\"Catherine\", \"Thomas\", \"Trevor\"]`)\n4. ένα object με δικά του πεδία (`\"address\": { ... }`)\n\nΠαρατηρήστε ότι ο παραπάνω ορισμός είναι αυτο-αναφορικός (ένα JSON object μπορεί να\nπεριέχει ένα πεδίο τύπου JSON object, που μπορεί να περιέχει ένα JSON object κοκ).\n\nΤι σχέση έχουν όλα αυτά με την τεχνητή νοημοσύνη; Προκειμένου να χρησιμοποιήσουμε τις\nυπηρεσίες τεχνητής νοημοσύνης πρέπει να μπορούμε να εξάγουμε κάποια συγκεκριμένα\nδεδομένα από ένα JSON. Για παράδειγμα, δείτε το παρακάτω παράδειγμα-απάντηση του\ngpt-4o-mini μοντέλου τεχνητής νοημοσύνης στην ερώτηση \"Tell me a joke\":\n\n```text\n{\n  \"id\": \"chatcmpl-Ag5hb4g6PYiVpvBp3tuiJjqX9KjqN\",\n  \"object\": \"chat.completion\",\n  \"created\": 1734595059,\n  \"model\": \"gpt-4o-mini-2024-07-18\",\n  \"choices\": [\n    {\n      \"index\": 0,\n      \"message\": {\n        \"role\": \"assistant\",\n        \"content\": \"Why do programmers always mix up Halloween\n                    and Christmas?\\nBecause Oct 31 == Dec 25!\\n\",\n        \"refusal\": null\n      },\n      \"logprobs\": null,\n      \"finish_reason\": \"stop\"\n    }\n  ],\n  \"usage\": {\n    \"prompt_tokens\": 10,\n    \"completion_tokens\": 23,\n    \"total_tokens\": 33,\n    \"prompt_tokens_details\": {\n      \"cached_tokens\": 0,\n      \"audio_tokens\": 0\n    },\n    \"completion_tokens_details\": {\n      \"reasoning_tokens\": 0,\n      \"audio_tokens\": 0,\n      \"accepted_prediction_tokens\": 0,\n      \"rejected_prediction_tokens\": 0\n    }\n  },\n  \"system_fingerprint\": \"fp_6fc10e10eb\"\n}\n```\n\nΤο παραπάνω JSON φαίνεται χαοτικό στην αρχή, αλλά αν το κοιτάξετε καλύτερα θα βρείτε\nτο περιεχόμενο της απάντησης. Για να την ανιχνεύσουμε μαζί:\n\n- Στο πάνω επίπεδο, έχουμε ένα JSON object με ένα πεδίο \"choices\".\n  - Το πεδίο choices είναι τύπου λίστα (ξεκινά με ’\\[’) και το πρώτο στοιχείο\n    (index = 0) είναι επίσης JSON object.\n    - Το JSON object της λίστας choices έχει μέσα ένα πεδίο που λέγεται \"message\" το\n      οποίο είναι επίσης τύπου JSON object.\n      - Τέλος, το message έχει μέσα ένα πεδίο το οποίο λέγεται \"content\", το οποίο\n        περιέχει το string με την απάντησή μας μέσα σε double quotes: \"Why do\n        programmers always mix up Halloween and Christmas?\\\\n Because Oct 31 == Dec\n        25!\\\\n\" - παρατηρήστε ότι οι αλλαγές γραμμής είναι escaped όπως θα ήταν σε\n        ένα string που θα γράφαμε σε πρόγραμμα σε γλώσσα C.\n\nΈνας πιο γρήγορος τρόπος να συμβολίσουμε το παραπάνω πεδίο είναι ως εξής:\n`json.choices[0].message.content` - μετάφραση: στο JSON αρχείο που μας δίνεται, θέλουμε\nνα βρούμε την λίστα choices, να πάρουμε το πρώτο στοιχείο της, από εκεί να πάρουμε το\nmessage και στο τέλος να πάρουμε την τιμή του content. Αν είχαμε την δυνατότητα να\nπάρουμε οποιοδήποτε αρχείο JSON και να εξάγουμε αυτήν την πληροφορία θα μπορούσαμε να\nφτιάξουμε το δικό μας chatbot!\n\nΑυτό θα είναι και ο στόχος αυτής της άσκησης, θα υλοποιήσουμε ένα πρόγραμμα το οποίο\nθα εξάγει την παραπάνω πληροφορία από αρχεία JSON και θα την αξιοποιεί για να δώσει\nαπαντήσεις στον χρήστη.\n\n### Τεχνικές Προδιαγραφές\n\n- Repository Name: progintro/hw2-\\<YourUsername\\>\n- C Filepath: jason/src/jason.c\n- Το πρόγραμμά θα έχει δύο modes:\n  - **Extraction mode**. Το πρόγραμμά σας μπαίνει σε extraction mode όταν ο χρήστης\n    δώσει το option `--extract`. Το option `--extract` περιμένει στην συνέχεια το\n    όνομα του αρχείου που περιέχει τα περιεχόμενα JSON και από τα οποία θα πρέπει να\n    εξάγετε το `json.choices[0].message.content` και να το τυπώσετε στην πρότυπη\n    έξοδο. Εάν δωθεί οποιοδήποτε αρχείο που δεν είναι valid JSON, το πρόγραμμά σας\n    πρέπει να τυπώσει μήνυμα ίδιο με τα παραδείγματα παρακάτω στο stderr.\n  - **Conversation mode**. Το πρόγραμμά σας μπαίνει σε διαδικασία συζήτησης με τον\n    χρήστη όταν δωθεί το option `--bot` χωρίς άλλα ορίσματα. Στην διαδικασία\n    συζήτησης, το πρόγραμμά σας ρωτάει επαναλαμβανόμενα τον χρήστη\n    `> What would you like to know?` μέχρι να στείλει ο χρήστης End-of-File (EOF).\n    Κάθε ερώτηση του χρήστη τελειώνει με καινούρια γραμμή και πρέπει να στέλνεται\n    αυτούσια στην κατάλληλη συνάρτηση της βιβλιοθήκης neurolib (δες παρακάτω).\n- Για τις διαδράσεις με το σύστημα τεχνητής νοημοσύνης (conversation mode) είναι\n  υποχρεωτικό να χρησιμοποιήσετε την βιβλιοθήκη neurolib (neurolib.c και neurolib.h)\n  που σας δίνεται στον φάκελο jason/src. Δυστυχώς κατεβάσαμε αυτήν την βιβλιοθήκη από\n  ένα online project χωρίς καθόλου documentation / testing. Προκειμένου να την\n  αξιοποιήσετε θα χρειαστεί να διαβάσετε τις διαθέσιμες συναρτήσεις στο header file\n  της και να ανακαλύψετε την χρήση τους. Ο στόχος σας είναι να στείλετε queries στην\n  υπηρεσία τεχνητής νοημοσύνης και να πάρετε JSON απαντήσεις.\n- Το αρχείο C που θα υποβληθεί πρέπει να μεταγλωττίζεται χωρίς ειδοποιήσεις για λάθη\n  και με κωδικό επιστροφής (exit code) που να είναι 0. Συγκεκριμένα, το αρχείο σας\n  **πρέπει** να μπορεί να μεταγλωττιστεί επιτυχώς με τις ακόλουθες εντολές σε ένα από\n  τα μηχανήματα του εργαστηρίου (linuxXY.di.uoa.gr) - για παράδειγμα το linux14:\n\n  ```sh\n  gcc -Wall -Wextra -Werror -pedantic -c neurolib.c\n  gcc -Wall -Wextra -Werror -pedantic -c jason.c\n  gcc -o jason neurolib.o jason.o -lssl -lcrypto\n  ```\n- README Filepath: jason/README.md\n- Τα αρχεία JSON θα είναι μέχρι 1MB σε μέγεθος.\n- Πρέπει να ολοκληρώνει την εκτέλεση μέσα σε: 1 δευτερόλεπτο.\n- Το πρόγραμμά σας θα πρέπει να έχει τα λιγότερα δυνατά memory leaks.\n\nΠαραδείγματα εκτέλεσης ακολουθούν, πρώτα σε extraction mode:\n\n```text\n$ ./jason --extract json/1.json\nWhy do programmers always mix up Halloween and Christmas?\nBecause Oct 31 == Dec 25!\n$ echo $?\n0\n$ ./jason --extract json/2.json 2> stderr\n$ echo $?\n1\n$ cat stderr\nNot an accepted JSON!\n```\n\nΚαι στην συνέχεια σε conversation mode:\n\n```text\n$ ./jason --bot\n> What would you like to know? What is the last digit of pi?\nI’d answer that, but I don’t want to ruin the surprise.\n> What would you like to know? What is the age of the universe?\nI could tell you, but then I’d have to awkwardly dance away without explaining why.\n> What would you like to know? Terminating\n```\n\nΉ μπορείτε να αλληλεπιδράσετε με μια πραγματική υπηρεσία τεχνητής νοημοσύνης (αν\nαγοράσετε tokens):\n\n```text\n$ export OPENAI_API_KEY=... # enter your key here\n$ ./jason --bot\n> What would you like to know? What is the last digit of pi?\nPi (pi) is an irrational number, which means it has an infinite\nnumber of decimal places and does not terminate. Therefore, it\ndoes not have a last digit. The decimal representation of pi begins\nwith 3.14159 and continues indefinitely without repeating.\n> What would you like to know? What is the age of the universe?\nAs of my last knowledge update in October 2023, the age of the\nuniverse is estimated to be about 13.8 billion years. This estimate\nis based on measurements of the cosmic microwave background radiation,\nthe expansion rate of the universe (Hubble constant), and observations\nof the oldest known star clusters. However, scientific understanding is\nalways evolving, so it's possible that new discoveries could refine\nthis estimate in the future.\n> What would you like to know? Terminating\n```\n\nΑν φτάσατε μέχρι εδώ: (1) συγχαρητήρια, (2) μην ξεχάσετε το README.md και (3) όπως\nπάντα ο κώδικας απαιτείται να είναι καλά τεκμηριωμένος με σχόλια καθώς αυτό θα είναι\nμέρος της βαθμολόγησης.",
  "hint": "Διαβάστε όλο το αρχείο σε ένα δυναμικό buffer και γράψτε έναν μικρό αναδρομικό\nparser (recursive descent) με μία συνάρτηση ανά είδος τιμής (object, array, string,\nαριθμός, literal), που προχωρά έναν δείκτη πάνω στο κείμενο και αποτυγχάνει μόλις\nκάτι δεν ταιριάζει. Δεν χρειάζεται να χτίσετε όλο το δέντρο: αρκεί να ακολουθήσετε\nτη διαδρομή `choices` → `[0]` → `message` → `content` και να μετατρέψετε τα escapes\n(`\\n`, `\\\"`, `\\\\`, …) κατά την εκτύπωση. Για το `--bot`, ξεκινήστε από το\n`neurolib.h`, και ελέγξτε με valgrind ότι ελευθερώνετε κάθε απάντηση."
 },
 {
  "id": "hw-2024-hw3-chess",
  "kind": "homework",
  "title": "Νέα Μηχανή Σκακιού (chess engine)",
  "source": {
   "title": "Εργασία 3 (2024-25), Άσκηση 1",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2024/hw3.pdf",
   "years": [
    2024
   ]
  },
  "chapters": [
   22,
   23,
   26
  ],
  "topics": [
   "game-ai",
   "recursion",
   "multidim-arrays",
   "strings",
   "code-organization",
   "make"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α22.16",
  "path": "questions/homework/hw-2024-hw3-chess.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2024-hw3-chess.html",
  "statement": "**Νέα Μηχανή Σκακιού (chess engine - 100 Μονάδες)**\n\nΗ εργασία είναι **προαιρετικά ομαδική με ομάδες μέχρι 2 άτομα**. Για να είναι\nξεκάθαρο ποια άτομα συνεργάστηκαν, **κάθε repository πρέπει να έχει ένα AUTHORS\nαρχείο** με μία γραμμή για κάθε άτομο, με πρώτο το sdi σας, μετά το github username\nκαι τέλος το όνομά σας:\n\n```text\n$ cat AUTHORS\nsdi2400998,mourmourakis-2006,ΘΑΝΟΣ ΜΟΥΡΜΟΥΡΑΚΗΣ\nsdi2400999,xifias-2006,ΚΩΣΤΑΣ ΞΙΦΙΑΣ\n```\n\n**Υποβολές χωρίς σωστό AUTHORS αρχείο δεν θα εξεταστούν**. Αυτό ισχύει και για\nατομικές υποβολές.\n\nΤα περισσότερα παιχνίδια έχουν παρεμφερή δομή: (1) το παιχνίδι ξεκινάει σε μια αρχική\nκατάσταση, (2) ένας από τους παίκτες παίζει πρώτος επιλέγοντας μια από τις δυνατές\nκινήσεις που έχει στην διάθεσή του αλλάζοντας την κατάσταση του παιχνιδιού και (3)\nστην συνέχεια δίνει την σειρά του στον επόμενο παίκτη. Ο χώρος καταστάσεων ενός\nπαιχνιδιού μπορεί να φανταστεί σαν ένα m-αδικό δέντρο βάθους n (m οι επιλογές σε κάθε\nθέση, n οι γύροι), με περίπου $m^n$ καταστάσεις. Η τρίλιζα και η ντάμα έχουν \"λυθεί\"\n(διατρέξαμε όλον τον χώρο καταστάσεών τους), αλλά το σκάκι όχι: ο Claude Shannon\nεκτίμησε τις δυνατές παρτίδες στο $10^{120}$ και τις θέσεις της σκακιέρας στο\n$10^{40}$. Οι μηχανές σκακιού εξερευνούν αυτόν τον χώρο με τεχνικές αναζήτησης /\nευριστικές ([minimax](https://en.wikipedia.org/wiki/Minimax),\n[negamax](https://en.wikipedia.org/wiki/Negamax)) και με ιδιαίτερα αποδοτικές\nυλοποιήσεις, συνήθως σε C και C++.\n\nΠόσο εύκολο είναι να φτιάξουμε μια μηχανή σκακιού σήμερα; Μπορεί να κερδίσει σχετικά\nαπλούς αντιπάλους που απλά παίζουν τυχαίες κινήσεις; Αυτό θα είναι και το αντικείμενο\nαυτής της άσκησης, όπου καλείστε να υλοποιήσετε τον πυρήνα μιας μηχανής σκακιού.\nΕυτυχώς, δεν χρειάζεται να ξεκινήσετε από το μηδέν, μπορείτε να βρείτε στο διαδίκτυο\nπολλές πληροφορίες για το πως δομούνται σκακιστικές μηχανές καθώς και ποιες\nβελτιστοποιήσεις είναι δημοφιλείς ([Chess Programming Wiki](https://www.chessprogramming.org/)).\n\n### Τεχνικές Προδιαγραφές\n\n- Repository Name: progintro/hw3-\\<YourTeamName\\>\n- README Filepath: README.md\n- Όλα τα αρχεία κώδικα (.c και .h) που θα υλοποιήσετε πρέπει να τοποθετηθούν μέσα σε\n  έναν φάκελο `src`.\n- Το αρχείο C που θα υποβληθεί πρέπει να μεταγλωττίζεται χωρίς ειδοποιήσεις για λάθη\n  και με κωδικό επιστροφής (exit code) που να είναι 0. Συγκεκριμένα, το αρχείο σας\n  **πρέπει** να μπορεί να μεταγλωττιστεί επιτυχώς με την ακόλουθη εντολή σε ένα από τα\n  μηχανήματα του εργαστηρίου (linuxXY.di.uoa.gr): `make`\n\n  Στο repository της άσκησης σας δίνεται μια πιθανή οργάνωση κώδικα μαζί με ένα\n  Makefile. Μπορείτε να αλλάξετε τα πάντα στο project σας, αλλά θέλουμε να\n  επιβεβαιώσετε πως η εντολή `make` συνεχίζει να δουλεύει και να παράγει εκτελέσιμα από\n  την μηχανή σκακιού σας.\n- Το πρόγραμμά σας πρέπει να προσφέρει τις ακόλουθες δύο διεπαφές:\n  1. **Μέσω γραμμής εντολών.** Να δέχεται 3 ορίσματα από την γραμμή εντολών: fen moves\n     timeout. Το πρώτο όρισμα (fen) θα είναι η τρέχουσα κατάσταση της σκακιέρας σε\n     [Forsyth-Edwards Notation](https://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation).\n     Το δεύτερο όρισμα (moves) θα είναι όλες οι δυνατές κινήσεις για αυτήν την θέση σε\n     [standard algebraic notation](https://en.wikipedia.org/wiki/Algebraic_notation_(chess))\n     και χωρισμένες με τον κενό χαρακτήρα \" \". Τέλος, το 3ο όρισμα θα είναι ο χρόνος σε\n     δευτερόλεπτα που έχει το πρόγραμμά σας για να αποφασίσει ποια από τις δοθείσες\n     κινήσεις επιλέγει. Το πρόγραμμά σας πρέπει να τυπώνει την θέση (index) της κίνησης\n     που επιλέγει και στην συνέχεια να επιστρέφει με exit code 0.\n  2. **Μέσω κλήσης συνάρτησης (για χρήση σε Web Assembly).** Το πρόγραμμά σας πρέπει\n     να περιέχει μια συνάρτηση `int choose_move(char * fen, char * moves, int timeout)`\n     η οποία θα δέχεται ορίσματα με σημασιολογία όμοια με παραπάνω και θα επιστρέφει\n     το index της κίνησης που επιλέγει. Όταν γίνεται compile σε Web Assembly, το\n     πρόγραμμά σας θα πρέπει να αποφεύγει να τυπώνει στο stdout/stderr καθώς αυτά δεν\n     είναι επιτρεπτά σε αυτό το περιβάλλον.\n- Το πρόγραμμά σας πρέπει να κερδίζει αποφασιστικά (άνω του 60%) των παιχνιδιών με\n  αντίπαλο μια μηχανή Random, δηλαδή μια μηχανή που επιλέγει κινήσεις τυχαία.\n- Το πρόγραμμά σας όταν μεταγλωττιστεί δεν θα πρέπει να ξεπερνά το 1MB στον δίσκο.\n- Το πρόγραμμά / συνάρτησή σας πρέπει να ολοκληρώνει την εκτέλεση μέσα στον αριθμό\n  των δευτερολέπτων που δίνονται ως όρισμα.\n\nΠαρακάτω παραθέτουμε την αλληλεπίδραση με μια ενδεικτική λύση:\n\n```text\n$ make TARGET=engine\n$ ./engine \"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1\" \\\n           \"a3 a4 b3 b4 c3 c4 d3 d4 e3 e4 f3 f4 g3 g4 h3 h4 Na3 Nc3 Nf3 Nh3\" \\\n           3\n9\n```\n\nΠαρατηρούμε ότι δώσαμε στο πρόγραμμά μας (το οποίο ονομάσαμε engine) 3 ορίσματα: (1)\nτην αρχική μας σκακιέρα σε FEN format, (2) τις κινήσεις που μπορεί να παίξει\nχωρισμένες με κενό (20 στον αριθμό) και (3) 3 δευτερόλεπτα για να αποφασίσει ποια\nκίνηση επιθυμεί να παίξει. Το πρόγραμμά μας αποφάσισε να παίξει την κίνηση στην θέση\n9 (προσοχή οι κινήσεις ξεκινάνε από το 0) και επομένως επέλεξε την κίνηση e4 (να\nκινήσει επομένως το λευκό πιόνι κατά δύο τετράγωνα μπροστά). Αυτό ήταν! Αν το\nπρόγραμμά σας υποστηρίζει την παραπάνω δυνατότητα (να τυπώνει τον σωστό ακέραιο),\nείναι σε θέση να χρησιμοποιηθεί ως μηχανή σκακιού. Το πόσο καλά θα τα πάει εξαρτάται\nαπό τις επιλογές που θα κάνει.\n\nΣτο αρχείο README.md πρέπει να προσθέσετε την περιγραφή του project σας καθώς και\nποιες πηγές χρησιμοποιήσατε κατά την υλοποίηση. Περιμένουμε να δούμε write ups υψηλής\nποιότητας, καθώς αυτό είναι ένα project που θα μπορούσατε να δημοσιεύσετε μετά το\nπέρας της άσκησης και να το βάλετε στο portfolio σας. Σκακιστικές μηχανές που\nεπιτυγχάνουν υψηλότερες επιδόσεις, θα πάρουν bonus μονάδες με μετρική που θα\nανακοινωθεί στην συνέχεια, (πιθανώς να χρησιμοποιήσουμε την μετρική\n[ELO](https://en.wikipedia.org/wiki/Elo_rating_system)).",
  "hint": "Χωρίστε το project σε ενότητες (αναπαράσταση σκακιέρας από FEN, παραγωγή και εκτέλεση\nκινήσεων, αξιολόγηση θέσης, αναζήτηση) με δικό του `.c`/`.h` η καθεμία. Ακόμη και μια\nαπλή αξιολόγηση με το υλικό (άθροισμα αξιών κομματιών) μαζί με minimax/negamax λίγων\nκινήσεων βάθους αρκεί για να κερδίζει μια τυχαία μηχανή· το alpha-beta pruning και η\nεπαναληπτική εκβάθυνση (iterative deepening) σας επιτρέπουν να σέβεστε το timeout.\nΠροσοχή: οι δοσμένες κινήσεις είναι σε SAN, οπότε πρέπει να τις αντιστοιχίσετε στις\nδικές σας, και η `choose_move` δεν πρέπει να τυπώνει τίποτα."
 },
 {
  "id": "hw-2025-bonus0-stergios",
  "kind": "homework",
  "title": "Ο Γρίφος του Στέργιου",
  "source": {
   "title": "Bonus #0 (2025-26, προαιρετική)",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/stergios.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   16,
   2,
   11
  ],
  "topics": [
   "math-algorithms",
   "problem-solving",
   "integer-representation",
   "recursion"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α16.18",
  "path": "questions/homework/hw-2025-bonus0-stergios.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2025-bonus0-stergios.html",
  "statement": "Ο Στέργιος μόλις έμαθε πρόσθεση και αφαίρεση στο σχολείο και βρήκε ένα καινούριο παιχνίδι:\nδιαλέγει στην τύχη τρεις αριθμούς, π.χ., το $(1, 2, 6)$ και σε κάθε βήμα μπορεί να\nαντικαταστήσει έναν από αυτούς (όποιον θέλει—έστω το 2) με το άθροισμα των άλλων ($1 + 6$)\nδύο φορές μείον τον εαυτό του ($1 + 6 + 1 + 6 - 2 = 12$) και παίρνει μια καινούρια τριάδα\n$(1, 12, 6)$. Αναρωτιέται αν κάνοντας τέτοια βήματα / επιλογές επανειλημμένα θα καταφέρει να\nμηδενίσει έναν από τους αριθμούς. Πέρα από αυτό, αναρωτιέται αν μπορεί να βρει την\nσυντομότερη σειρά επιλογών προκειμένου να μηδενίσει έναν εξ αυτών. Με δοκιμές παρατήρησε ότι\nγια τους αριθμούς $(1, 2, 6)$ η καλύτερη επιλογή είναι να διαλέξει το 6 πρώτα καθώς σε μόνο\nένα βήμα θα πάρει την τριάδα $(1, 2, 0)$.\n\nΈστω `stergios` η μαγική συνάρτηση που δίνει τον *ελάχιστο αριθμό βημάτων* προκειμένου να\nμηδενιστεί ένας από τους αριθμούς της αρχικής τριάδας. Για παράδειγμα,\n$stergios(0, 7, 9) = 0$, $stergios(1, 2, 6) = 1$, $stergios(1000, 216, 102) = 3$ (πως;). Αν\n*δεν* υπάρχει αριθμός βημάτων που να την μηδενίζει, τότε η συνάρτηση `stergios` πάλι\nεπιστρέφει μηδέν. Για παράδειγμα, $stergios(74, 214, 540) = 0$ (ο Στέργιος δεν βρήκε κάποιον\nτρόπο να φτάσει στο μηδέν με αυτούς τους τρεις αριθμούς όσο και αν προσπάθησε). Είναι εφικτό\nνα υπολογίσουμε αθροίσματα της συνάρτησης `stergios` για όλους τους αριθμούς αν κάποιες από\nτις αρχικές μας επιλογές είναι μεγάλοι ακέραιοι; Συγκεκριμένα, ο Στέργιος αναρωτιέται αν\nμπορούμε να υπολογίσουμε το άθροισμα:\n\n$$Solution = \\sum_{i=0}^{\\infty} stergios(i, 100000000000000000000, 3656158440062976)$$\n\nΟ μπαμπάς του, ο Μάκης, προσπάθησε, πρώτα μόνος και μετά με βοήθεια, αλλά δεν μπόρεσε να\nδώσει μια ικανοποιητική απάντηση. Μήπως μπορείτε εσείς; Τα τελευταία βράδια ο Μάκης βλέπει\nδιαρκώς στο όνειρό του ότι $\\sum_{i=0}^{\\infty} stergios(1000, 216, i) = 1051$ και επίσης πως\n$stergios(1000, 216, 109218) = 108$ αλλά δεν έχει καμία βεβαιότητα. Το μόνο που ξέρει είναι\nπως η τιμή του $Solution$ τυχαίνει να είναι και το password του χρήστη `impossible0` στο\nσύστημα `35.169.96.19` της Εργασίας 0.\n\nΗ πρώτη σωστή λύση στον παραπάνω γρίφο θα οδηγήσει σε Bonus μέχρι 360 μονάδες. Οι επόμενες\nλύσεις θα λάβουν επίσης bonus αναλογικά (η 2η μέχρι 360/2=180 μονάδες, η 3η μέχρι 360/3=120\nμονάδες κοκ). Το πρόβλημα θα κλείσει μόλις (εάν) βρεθούν 10 λύσεις ή τελειώσει το\nεξάμηνο—ότι από τα δύο συμβεί πιο γρήγορα.",
  "hint": "Ξεκίνα με ένα πρόγραμμα ωμής βίας (αναζήτηση κατά πλάτος στις τριάδες) για μικρούς αριθμούς\nκαι επιβεβαίωσε τα παραδείγματα και τις «ονειρικές» τιμές του Μάκη· μετά ψάξε δομή στα\nαποτελέσματα. Παρατήρησε ότι το βήμα $x \\to 2(y+z) - x$ είναι «ανάκλαση» και ότι κάνοντάς το\nδύο φορές στην ίδια θέση επιστρέφεις εκεί που ήσουν· σκέψου ποια ποσότητα των τριών αριθμών\nμένει αναλλοίωτη και ποιο βήμα μικραίνει την τριάδα, ώστε να μην εξερευνάς τυφλά. Το\nάθροισμα είναι άπειρο αλλά μόνο πεπερασμένα $i$ δίνουν μη μηδενικό αποτέλεσμα, και οι τιμές\nξεπερνούν τα 64 bits, άρα χρειάζεσαι προσοχή με τους τύπους (π.χ. `__int128` ή δική σου\nαριθμητική)."
 },
 {
  "id": "hw-2025-hw0-aliquot",
  "kind": "homework",
  "title": "Οι Ακολουθίες Aliquot",
  "source": {
   "title": "Εργασία 0 (2025-26), Άσκηση 3",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/hw0.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   6,
   9,
   2
  ],
  "topics": [
   "loops",
   "math-algorithms",
   "integer-representation",
   "input-validation"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α6.15",
  "path": "questions/homework/hw-2025-hw0-aliquot.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2025-hw0-aliquot.html",
  "statement": "Στα μαθηματικά, η [ακολουθία aliquot](https://en.wikipedia.org/wiki/Aliquot_sequence) είναι\nμια ακολουθία θετικών ακεραίων στην οποία ο κάθε όρος είναι το άθροισμα των γνησίων\nδιαιρετών του προηγουμένου όρου (γνήσιοι διαιρέτες ενός αριθμού $n$ λέγονται όλοι οι\nακέραιοι διαιρέτες του $n$ πλην του εαυτού του). Αν η ακολουθία φτάσει στον αριθμό 1,\nτερματίζει, εφόσον το άθροισμα των γνησίων διαιρετών του 1 είναι 0. Συμβολίζοντας με\n$s(n)$ το άθροισμα των γνήσιων διαιρετών του $n$, για $n = 12$ έχουμε:\n\n$$s(12) = 1 + 2 + 3 + 4 + 6 = 16$$\n\nκαι συνεχίζοντας με τον ίδιο τρόπο $s(16) = 15$, $s(15) = 9$, $s(9) = 4$, $s(4) = 3$,\n$s(3) = 1$, $s(1) = 0$. Η ακολουθία τελικά φτάνει στο 0 μετά από 7 βήματα\n($12 \\to 16 \\to 15 \\to 9 \\to 4 \\to 3 \\to 1 \\to 0$). Ο αριθμός των βημάτων (ουσιαστικά ο\nαριθμός των μεταβάσεων $\\to$) που απαιτούνται για να μεταβεί ένας ακέραιος $n$ στο 0\nλέγεται **μήκος aliquot** για το δοθέν $n$. Με τον συμβολισμό $s^m(n) = s(s(\\cdots s(n)\\cdots))$\n($m$ φορές) γράφουμε $s^2(12) = 15$ ή $s^7(12) = 0$· ισοδύναμα, το μήκος aliquot $l$ είναι ο\nμικρότερος ακέραιος $l$ για τον οποίο $s^l(n) = 0$.\n\nΔεν είναι όλες οι ακολουθίες aliquot φθίνουσες. Για τους τέλειους αριθμούς όπως το 6\n($s(6) = 1 + 2 + 3 = 6$) η ακολουθία δεν τερματίζει ποτέ, καθώς $s^m(6) = 6$ για κάθε $m$.\nΥπάρχουν και οι φίλιοι αριθμοί όπως οι 220 και 284 ($220 \\to 284 \\to 220 \\to \\cdots$) και\nοι κοινωνικοί αριθμοί με κύκλους μεγαλύτερης περιοδικότητας. Η εικασία Catalan-Dickson\n(1888) λέει ότι κάθε ακολουθία είτε φτάνει στο 0 είτε πέφτει σε κύκλο, και ακόμα δεν έχει\nαποδειχθεί. Για κάποιους σχετικά μικρούς αριθμούς, όπως ο 276, δεν έχουμε καταφέρει ακόμα\nνα υπολογίσουμε την πλήρη ακολουθία!\n\nΘα χρειαστεί να υλοποιήσετε ένα πρόγραμμα το οποίο να μπορεί να υπολογίζει τους όρους και\nτα μήκη της ακολουθίας aliquot για τους αριθμούς που επιλέγει ο χρήστης, με τους\nπεριορισμούς των τεχνικών προδιαγραφών που ακολουθούν.\n\n### Τεχνικές Προδιαγραφές\n\n- Repository Name: `progintro/hw0-<YourUsername>`\n- Αρχείο C (Filepath): `aliquot/src/aliquot.c`\n- Το αρχείο C που θα υποβληθεί πρέπει να μεταγλωττίζεται χωρίς ειδοποιήσεις για λάθη και\n  με κωδικό επιστροφής (exit code) που να είναι 0. Συγκεκριμένα, το αρχείο σας **πρέπει**\n  να μπορεί να μεταγλωττιστεί επιτυχώς με την ακόλουθη εντολή σε ένα από τα μηχανήματα\n  του εργαστηρίου (linuxXY.di.uoa.gr):\n  `gcc -O0 -m32 -Wall -Wextra -Werror -pedantic -o aliquot aliquot.c`\n- README Filepath: `aliquot/README.md`\n- Το πρόγραμμά σας πρέπει να διαβάζει από την πρότυπη είσοδο (stdin) 3 διαφορετικές\n  τιμές:\n  1. Τον θετικό ακέραιο από τον οποίο θέλετε να ξεκινήσετε την ακολουθία.\n  2. Το μέγιστο μήκος της ακολουθίας (το 0 θα συμβολίζει ότι επιτρέπεται ακολουθίες\n     \"άπειρου\" μήκους) που θέλουμε να υπολογιστεί.\n  3. Έναν χαρακτήρα που να δηλώνει αν θέλετε το πρόγραμμά σας να τυπώσει την πλήρη\n     ακολουθία `'f'` (full) ή να τυπώσει μόνο το μήκος της `'l'` (length).\n- Δείτε παραδείγματα από τις πρότυπες εκτελέσεις παρακάτω για να δείτε την αναμενόμενη\n  έξοδο.\n- Όλοι οι ακέραιοι που θα δοθούν στο πρόγραμμά σας θα είναι ακέραιοι μικρότεροι από\n  $10^{15}$. Αν κατά την διαδικασία του υπολογισμού της ακολουθίας το πρόγραμμά σας φτάσει\n  σε ακέραιο μεγαλύτερο του $10^{15}$, το πρόγραμμά σας πρέπει να τερματίσει με μήνυμα\n  λάθους και κωδικό εξόδου (exit code) 1.\n- Αν δοθεί οποιαδήποτε είσοδος εκτός προδιαγραφών (για παράδειγμα ο χρήστης δεν δώσει\n  κάποιον ακέραιο για να υπολογιστεί η ακολουθία) το πρόγραμμά σας πρέπει να τερματίζει\n  με κωδικό εξόδου (exit code) 1.\n- Για μια ακολουθία μήκους $n$, οι χρήστες αναμένουν πως το πρόγραμμά σας πρέπει να\n  ολοκληρώνει την εκτέλεσή του μέσα σε λιγότερο από $n$ δευτερόλεπτα.\n\nΠαρακάτω παραθέτουμε αλληλεπιδράσεις με μια ενδεικτική λύση:\n\n```text\n$ hostname\nlinux14\n$ gcc -O0 -m32 -Wall -Wextra -Werror -pedantic -o aliquot aliquot.c\n$ ./aliquot\nPlease give the number to start the aliquot sequence from: 12\nProvide the max aliquot length to look for (0 for unlimited): 0\nDo you want to print the full sequence ('f') or just the length ('l')? f\n12\n16\n15\n9\n4\n3\n1\n0\n$ ./aliquot\nPlease give the number to start the aliquot sequence from: 12\nProvide the max aliquot length to look for (0 for unlimited): 0\nDo you want to print the full sequence ('f') or just the length ('l')? l\nLength of aliquot sequence: 7\n$ echo $?\n0\n$ ./aliquot\nPlease give the number to start the aliquot sequence from: 138\nProvide the max aliquot length to look for (0 for unlimited): 200\nDo you want to print the full sequence ('f') or just the length ('l')? l\nLength of aliquot sequence: 178\n$ ./aliquot\nPlease give the number to start the aliquot sequence from: 6\nProvide the max aliquot length to look for (0 for unlimited): 6\nDo you want to print the full sequence ('f') or just the length ('l')? f\n6\n6\n6\n6\n6\n6\n6\n$ ./aliquot\nPlease give the number to start the aliquot sequence from: 276\nProvide the max aliquot length to look for (0 for unlimited): 0\nDo you want to print the full sequence ('f') or just the length ('l')? f\n276\n396\n...\n749365894850244\n1414070378301756\nNumber exceeds maximum supported integer (1000000000000000). Stopping.\n$ echo $?\n1\n```\n\nΣτο αρχείο `README.md` πρέπει να προσθέσετε οποιεσδήποτε παρατηρήσεις σας κατά την\nδιεκπεραίωση της άσκησης. Ο κώδικας απαιτείται να είναι καλά τεκμηριωμένος με σχόλια\nκαθώς αυτό θα είναι μέρος της βαθμολόγησης.",
  "hint": "Με `-m32` ο `long` έχει 32 bits, οπότε τιμές μέχρι $10^{15}$ θέλουν `long long` (και\n`%lld` στο `scanf`/`printf`). Για το $s(n)$ μη δοκιμάσεις όλους τους διαιρέτες μέχρι το\n$n$: οι διαιρέτες έρχονται σε ζεύγη $d$ και $n/d$, άρα αρκεί να φτάσεις ως το $\\sqrt{n}$,\nπροσέχοντας τα τέλεια τετράγωνα και ότι ο ίδιος ο $n$ δεν μετράει. Έλεγξε την τιμή\nεπιστροφής κάθε `scanf` και σκέψου τις ακραίες περιπτώσεις: $n = 1$, μέγιστο μήκος 0,\nχαρακτήρας διαφορετικός από `f`/`l`."
 },
 {
  "id": "hw-2025-hw0-cmdline",
  "kind": "homework",
  "title": "Παιχνίδια με Κονσόλα (cmdline)",
  "source": {
   "title": "Εργασία 0 (2025-26), Άσκηση 2",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/hw0.pdf",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   1,
   4
  ],
  "topics": [
   "shell",
   "unix",
   "redirection",
   "git",
   "compilation"
  ],
  "difficulty": 2,
  "type": "tooling",
  "label": "Α1.12",
  "path": "questions/homework/hw-2025-hw0-cmdline.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2025-hw0-cmdline.html",
  "statement": "Έχεις χρησιμοποιήσει την γραμμή εντολών; Linux; Γνωρίζεις πως να κάνεις SSH σε\nαπομακρυσμένους servers και να λύνεις προβλήματα με εντολές κονσόλας; Αν όχι, καιρός να\nμάθουμε! Αν ναι, τότε αυτή η άσκηση θα σου είναι παιχνιδάκι.\n\nΣε αυτήν την άσκηση θα μπούμε με ssh σε έναν απομακρυσμένο server που βρίσκεται στην IP\nδιεύθυνση `35.169.96.19` μέσω τερματικού και θα ανακτήσουμε συγκεκριμένες πληροφορίες.\nΥπάρχουν διαφορετικοί χρήστες (`byte0`, `byte1`, …) που αντιστοιχούν σε διαφορετικά\nπροβλήματα/υποερωτήματα. Για όλους τους χρήστες ο κωδικός για να μπείτε είναι\n`bits&bytes`. Σε κάθε ένα υποερώτημα θα αναζητούμε ένα string που μπορεί να είναι μια\nμόνο λέξη ή πολλές λέξεις διαχωρισμένες με τον χαρακτήρα underscore `_`, για παράδειγμα:\n`something_like_that`.\n\n### byte0: Αλλάζοντας Φάκελο (cd)\n\nΟ χρήστης byte0 είναι ελαφρώς μανιακός με την οργανωτικότητα. Του αρέσει να οργανώνει όλα\nτου τα αρχεία σε φακέλους, υποφακέλους κ.ο.κ.. Με αυτά και με αυτά όμως, δεν μπορεί να βρει\nτο αρχείο του, μπορείτε να τον βοηθήσετε; Για να μπείτε στον server τρέξτε:\n\n```text\nssh byte0@35.169.96.19\n```\n\nκαι βάλτε τον κωδικό που γράψαμε παραπάνω. Η εντολή `cd` μπορεί να σας φανεί χρήσιμη όπως\nκαι η εντολή `cat` (ίσως και το tab / autocomplete :)). Όταν διαβάσετε τα περιεχόμενα του\nαρχείου, σημειώστε το string που βρήκατε μέσα στο αρχείο ώστε να το προσθέσετε στο\n`solution.txt` (δες παρακάτω στις τεχνικές προδιαγραφές).\n\n### byte1: Μια Εντολή Άγνωστη\n\nΟ χρήστης byte1 έφτιαξε ένα καινούριο πρόγραμμα με άγνωστη σε μας λειτουργία ονόματι\n`supercalifragilisticexpialidocious`. Πως μπορείτε να βρείτε τι κάνει;\n\n### byte2: Τα Άπαντα του Shakespeare (grep)\n\nΟ χρήστης byte2 έχει δύο βασικά χαρακτηριστικά: (1) είναι μεγάλος θαυμαστής του\nShakespeare και (2) είναι κάπως μυστικοπαθής. Αποφάσισε να συνδυάσει τα δύο και\nκαταχώνιασε ένα μυστικό string μέσα στην συλλογή του με τα άπαντα του Shakespeare.\nΜπορείτε να τον βοηθήσετε να το βρεί;\n\nΤο μόνο που γνωρίζουμε είναι πως το κρυφό κείμενο περιέχει το string \"will find\". Η\nεντολή `grep` μπορεί να σας φανεί χρήσιμη.\n\n### byte3: Τα Άπαντα του Shakespeare Άλλαξαν (diff)\n\nΟ χρήστης byte3 αποφάσισε να αλλάξει κάτι στα άπαντα του Shakespeare ελπίζοντας πως η\nαλλαγή θα περάσει απαρατήρητη. Ελέγξαμε τον αριθμό των λέξεων και χαρακτήρων του κάθε\nαρχείου:\n\n```text\nbyte3@ip-172-31-37-131:~$ wc -w *.txt\n  901325 shakespeare.modified.txt\n  901325 shakespeare.txt\n 1802650 total\nbyte3@ip-172-31-37-131:~$ wc -c *.txt\n 5458203 shakespeare.modified.txt\n 5458199 shakespeare.txt\n```\n\nκαι παρατηρήσαμε πως ενώ ο αριθμός λέξεων παρέμεινε ίδιος (901.325), ο αριθμός των\nχαρακτήρων άλλαξε. Επομένως, υποψιαζόμαστε πως άλλαξε μια λέξη του αυθεντικού με μια\nκαινούρια. Βρείτε την καινούρια λέξη—η εντολή `diff` ίσως σας φανεί χρήσιμη.\n\n### byte4: Λαβύρινθος (find)\n\nΟ χρήστης byte4 είναι συγγενής του byte2 παραπάνω και ελαφρώς πιο μυστικοπαθής.\nΠροκειμένου να \"ανεβάσει\" το παιχνίδι του αποφάσισε να κρύψει τα δεδομένα του σε ένα\nδαιδαλώδες κατασκεύασμα από φακέλους. Μπορείτε και πάλι να τον βοηθήσετε να βρει το\nμυστικό που έχει κρύψει μέσα σε ένα από όλα τα αρχεία των υποφακέλων; Το μόνο που\nγνωρίζουμε είναι πως έχει κρύψει το μυστικό του σε ένα αρχείο που λέγεται `cup.txt`. Η\nεντολή `find` μπορεί να σας φανεί χρήσιμη.\n\n### byte5: Compile and Run (gcc, mkdir, cp)\n\nΟ byte5 έγραψε ένα προγραμματάκι σε C ονόματι `byte5.c`. Μεταγλωττίστε το και τρέξτε το\nπροκειμένου να πάρετε τον κωδικό σας! Προσοχή: ο default φάκελος του byte5 δεν σας\nεπιτρέπει να χρησιμοποιήσετε αρχεία, ίσως χρειαστεί να φτιάξετε έναν καινούριο υποφάκελο\nμέσα στον φάκελο `/tmp` προκειμένου να τοποθετήσετε το εκτελέσιμό σας. Οι εντολές\n`mkdir`, `cp`, `gcc` μπορεί να σας φανούν χρήσιμες.\n\n### byte6: Αποσυμπίεση αρχείου 1 (unzip)\n\nΚάποιες φορές προκειμένου να μικρύνουμε τον χώρο που πιάνει ένα αρχείο το συμπιέζουμε. Ο\nχρήστης byte6 έχει ένα αρχείο `byte6.zip` το οποίο χρειάζεται αποσυμπίεση. Ανοίξτε το για\nνα αποκτήσετε πρόσβαση στα περιεχόμενά του. Το πρόγραμμα `unzip` μπορεί να σας βοηθήσει.\n\n### byte7: Αποσυμπίεση αρχείου 2 (tar)\n\nΥπάρχουν διάφοροι τρόποι και εργαλεία για να συμπιέσεις αρχεία και τα περιεχόμενα τους.\nΟ χρήστης byte7 χρησιμοποίησε ένα πρόγραμμα που λέγεται `tar` - μπορείτε να\nχρησιμοποιήσετε το ίδιο προκειμένου να βρείτε τα περιεχόμενα του `byte7.tar.gz`;\n\n### byte8: Carriage Return (xxd, pico, vim)\n\nΟ χρήστης byte8 μας είπε πως ο κωδικός που ψάχνουμε είναι μέσα στο αρχείο\n`carriage_return.txt`. Όμως δοκιμάσαμε να το τυπώσουμε:\n\n```text\nbyte8@ip-172-31-37-131:~$ ls\ncarriage_return.txt\nbyte8@ip-172-31-37-131:~$ cat carriage_return.txt\nThere is absolutely nothing to see here. Move along.\n```\n\nκαι δεν είδαμε κάτι. Μπορείς να μας βοηθήσεις; Πιστεύουμε πως οι εντολές `xxd`, `pico` ή\n`vim` μπορεί να φανούν χρήσιμες.\n\n### byte9: Ένα Περίεργο Όνομα (cat)\n\nΟ χρήστης byte9 ανέφερε πως ο κωδικός του είναι μέσα στον φάκελο `/home/byte9` - μπορείς\nνα μας βοηθήσεις να τον ανακτήσουμε; Ίσως σε βοηθήσει να θυμηθείς τι είναι το filepath\n(μονοπάτι) ενός αρχείου.\n\n### byte10: Το 42ο Όνομα (sort, head)\n\nΟ χρήστης byte10 έχει ένα αρχείο γεμάτο με ονόματα και θέλει να τα ταξινομήσει αλφαβητικά\nκαι να βρει το 42ο όνομα στην σειρά. Γνωρίζει ότι το 1ο όνομα είναι το Aarika - μπορείτε\nνα τον βοηθήσετε να βρει το 42ο; Οι εντολές `sort` και `head` μπορούν να συνδυαστούν και\nνα βοηθήσουν.\n\n### byte11: Επιλογές Ονόματος (sort, uniq)\n\nΟ χρήστης byte11 μόλις απέκτησε ένα παιδάκι και προκειμένου να μην το κοροϊδεύουν στο\nσχολείο αποφάσισε να του δώσει το πιο συχνό όνομα εκείνης της χρονιάς. Στο αρχείο\n`births.txt` περιέχονται τα ονόματα όλων των φετινών γεννήσεων. Μπορείτε να τον βοηθήσετε\nνα βρει το πιο συχνό όνομα; Οι εντολές `sort` και `uniq` ίσως σας φανούν χρήσιμες.\n\n### byte12: Βρες το Μονοπάτι (which, PATH)\n\nΟ byte12 είναι κάπως αφηρημένος. Μόλις έφτιαξε το πρόγραμμα `tuxsay` αλλά δεν θυμάται που\nτο τοποθέτησε και δεν πρόλαβε να φτιάξει ένα manual page. Παρόλα αυτά, μπορεί να το τρέξει\nκανονικά. Μπορείτε να βρείτε το basename του φακέλου μέσα στον οποίο βρίσκεται το\nπρόγραμμα `tuxsay`;\n\n### byte13: Commit Messages (git log)\n\nΟ byte13 μόλις πήρε πρόσβαση σε ένα git repository (αποθετήριο) και θέλει να δει τα commit\nmessages (μηνύματα για προηγούμενες αλλαγές) που έκαναν οι χρήστες που συνεισέφεραν στο\nrepository. Μπορείτε να διαβάσετε αυτά τα μηνύματα;\n\n### byte14: Ιστορικό (git log -p)\n\nΟ byte14 ξεκίνησε να γράφει μια νουβέλα με την βοήθεια του ΑΙ. Μετά από αρκετές αλλαγές\nδιαπίστωσε ότι το ΑΙ είχε προσθέσει (κατά λάθος;) έναν από τους κωδικούς του μέσα στο\nκείμενο. Ευτυχώς το είδε, το αφαίρεσε, έκανε commit τις αλλαγές και πλέον ξέρει δεν είναι\nορατό σε άλλους χρήστες. Έχει δίκιο ο byte14;\n\n### byte15: Open the Vault (bonus / προαιρετικό)\n\nΟ byte15 είναι χρήστης του vault, ενός υπερασφαλούς προγράμματος που εμφανίζει τα\nπεριεχόμενα του λογαριασμού σου, μόνο εφόσον γνωρίζεις το μυστικό PIN. Δυστυχώς, ο byte15\nξέχασε το PIN του! Μπορείτε να τον βοηθήσετε να ανακτήσει τα περιεχόμενα του λογαριασμού\nτου;\n\n### Τεχνικές Προδιαγραφές\n\nΗ υποβολή σου πρέπει να έχει τα ακόλουθα χαρακτηριστικά:\n\n- Repository Name: `progintro/hw0-<YourUsername>`\n- README Filepath: `cmdline/README.md`\n- Αρχείο Λύσης Filepath: `cmdline/solution.txt`\n- **Κάθε γραμμή που θα προστεθεί στο αρχείο `solution.txt` πρέπει να γίνει με\n  διαφορετικό git commit. Κοινώς, θέλουμε να δούμε τουλάχιστον \\*15\\* διαφορετικά git\n  commits. Η κάθε γραμμή πρέπει να προστεθεί όταν λύσετε το αντίστοιχο πρόβλημα, όχι όλες\n  μαζί στο τέλος.**\n\nΤο περιεχόμενο του `solution.txt` πρέπει να έχει την ακόλουθη μορφή:\n\n```text\n$ cat solution.txt\nbyte0: ...\nbyte1: ...\nbyte2: ...\n...\n```\n\nΌπου οι τελείες (...) περιγράφουν το μέρος της λύσης που έχει παραληφθεί. Στο αρχείο\n`README.md` πρέπει να γράψετε μια σύντομη περιγραφή για τον τρόπο που λύσατε το κάθε\nπρόβλημα.\n\nΑν σου άρεσε αυτή η άσκηση ή έχεις κολλήσει με ένα από τα παραπάνω και δεν ξέρεις πως να\nσυνεχίσεις, υπάρχουν και άλλα site online στα οποία μπορείς να εξασκηθείς όπως για\nπαράδειγμα το [overthewire](https://overthewire.org/wargames/bandit/bandit0.html) τα οποία\nμπορούν να σου δώσουν ιδέες. Σημείωση: μέχρι το επίπεδο 11 τα προβλήματα σε αυτό το site\nείναι εντός θέματος για το μάθημα, από εκεί και πέρα γίνονται πιο δύσκολα / απαιτούν\nγνώσεις που θα αποκτήσουμε σε μεγαλύτερα έτη.\n\n## Εμφανίσεις\n\n- [Εργασία 0 (2024-25), Άσκηση 2](https://github.com/progintro/progintro.github.io/releases/download/2024/hw0.pdf): 12 επίπεδα (`byte0`–`byte11`) στον server `52.86.144.139`, 12 commits· το `byte10` ζητά το 10ο όνομα αντί για το 42ο.\n- [Εργασία 0 (2025-26), Άσκηση 2](https://github.com/progintro/progintro.github.io/releases/download/2025/hw0.pdf): η εκφώνηση που δίνεται εδώ, με τα νέα επίπεδα `byte12`–`byte15` (`which`/`PATH`, `git log`, `git log -p`, bonus vault) και τουλάχιστον 15 commits.",
  "hint": "Κάθε επίπεδο δοκιμάζει μία ή δύο εντολές, και το `man <εντολή>` (ή το `--help`) είναι ο\nπρώτος σου σύμμαχος, ακόμα και για άγνωστα προγράμματα. Για τα επίπεδα με πολλά δεδομένα\nσυνδύασε εντολές με σωληνώσεις (`|`), π.χ. ταξινόμηση πριν από μέτρηση διπλοτύπων. Τα\nονόματα αρχείων που αρχίζουν με παύλα ή έχουν κενά, τα κρυφά αρχεία (τελεία στην αρχή), οι\nχαρακτήρες ελέγχου μέσα σε ένα αρχείο και το ιστορικό ενός git repository είναι οι\nσυνηθισμένες «παγίδες» που αξίζει να έχεις στο μυαλό σου."
 },
 {
  "id": "hw-2025-hw0-pages",
  "kind": "homework",
  "title": "Νέο URL στο GitHub (pages)",
  "source": {
   "title": "Εργασία 0 (2025-26), Άσκηση 1",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/hw0.pdf",
   "years": [
    2023,
    2024,
    2025
   ]
  },
  "chapters": [
   4,
   1
  ],
  "topics": [
   "git",
   "shell"
  ],
  "difficulty": 1,
  "type": "tooling",
  "label": "Α4.12",
  "path": "questions/homework/hw-2025-hw0-pages.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2025-hw0-pages.html",
  "statement": "Έχεις λογαριασμό στο GitHub; Έχεις ξαναφτιάξει repository; Έχεις φτιάξει URL στο\nδιαδίκτυο; Μετά από αυτήν την άσκηση θα μπορείς να απαντήσεις \"ναι\" σε όλα.\n\nΗ ιστοσελίδα του μαθήματος βασίζεται σε ένα public GitHub repository. Σκοπός αυτής της\nάσκησης είναι να δημιουργήσεις ένα καινούριο repository στον προσωπικό σου λογαριασμό\nGitHub και να το συνδέσεις με GitHub Pages προκειμένου να είναι διαθέσιμο στο διαδίκτυο.\nΑυτό το [tutorial](https://docs.github.com/en/pages/quickstart) μπορεί να σε βοηθήσει.\n\n### Τεχνικές Προδιαγραφές\n\nΗ υποβολή σου πρέπει να έχει τα ακόλουθα χαρακτηριστικά:\n\n- Repository Name: `progintro/hw0-<YourUsername>`\n- Αρχείο Λύσης Filepath: `pages/solution.txt`\n- README Filepath (optional): `pages/README.md`\n\nΈστω ότι το GitHub username σου είναι `YourUsername`. Το αρχείο `solution.txt` πρέπει να\nπεριέχει το URL με το domain `YourUsername.github.io` που δημιουργήσατε. Αν\nχρησιμοποιήσετε κάποιο `*.github.io` URL που δεν δημιουργήσατε η άσκηση μηδενίζεται.\nΕνδεικτική συμπεριφορά για μια επιτυχημένη υποβολή (**προσοχή: η γραμμή με την εντολή\ncurl εκτείνεται σε δύο γραμμές, πρέπει να αντιγράψετε και τις δύο προκειμένου να τρέξετε\nαυτήν την εντολή**, το backslash `\\` δείχνει ότι η εντολή είναι μία αλλά εκτείνεται σε δύο\nγραμμές):\n\n```text\n# Check out solution URL\n$ cat solution.txt\nYourUsername.github.io\n# Ensure the URL exists\n$ curl --output /dev/null --silent --head --fail YourUsername.github.io && \\\n  echo \"URL exists\" || echo \"URL does not exist\"\nURL exists\n```\n\nΤο αρχείο `README.md` είναι προαιρετικό αν θέλετε να προσθέσετε κάτι στην υποβολή σας.\n\n## Εμφανίσεις\n\n- [Εργασία 0 (2023-24), Άσκηση 1](https://github.com/progintro/progintro.github.io/releases/download/2023/hw0.pdf): ίδια εκφώνηση, χωρίς τον σύνδεσμο προς το tutorial του GitHub Pages.\n- [Εργασία 0 (2024-25), Άσκηση 1](https://github.com/progintro/progintro.github.io/releases/download/2024/hw0.pdf): ίδια εκφώνηση (20 μονάδες).\n- [Εργασία 0 (2025-26), Άσκηση 1](https://github.com/progintro/progintro.github.io/releases/download/2025/hw0.pdf): η εκφώνηση που δίνεται εδώ.",
  "hint": "Το GitHub Pages σερβίρει αυτόματα ένα repository με όνομα ακριβώς `<username>.github.io`\nστον λογαριασμό σου, αρκεί να περιέχει ένα αρχείο όπως το `index.html`. Δοκίμασε το URL\nμε την εντολή `curl` της εκφώνησης πριν το γράψεις στο `solution.txt`, και θυμήσου ότι το\n`solution.txt` ζει σε άλλο repository (το `hw0-<YourUsername>`), οπότε χρειάζεσαι\n`git add`, `commit` και `push` και εκεί."
 },
 {
  "id": "hw-2025-hw1-soundwave",
  "kind": "homework",
  "title": "Επεξεργασία Ήχου (soundwave)",
  "source": {
   "title": "Εργασία 1 (2025-26), Άσκηση 1",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/hw1.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   9,
   12,
   5
  ],
  "topics": [
   "image-audio",
   "input-output",
   "command-line-args",
   "bitwise",
   "floating-point"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α9.17",
  "path": "questions/homework/hw-2025-hw1-soundwave.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2025-hw1-soundwave.html",
  "statement": "Ο ήχος είναι ένα αναλογικό σήμα, μια συνάρτηση $f(t)$ της έντασης ως προς τον χρόνο, που\nγια να αποθηκευθεί σε υπολογιστή ψηφιοποιείται καταγράφοντας την τιμή του σε διακριτές\nισαπέχουσες χρονικές στιγμές (π.χ. 44.100 δείγματα ανά δευτερόλεπτο σε ένα μουσικό CD).\nΑντικείμενο αυτής της εργασίας είναι η δημιουργία *ενός συστήματος επεξεργασίας ήχου για\nαρχεία τύπου wav*.\n\n### Η μορφή των αρχείων wav\n\nΤα αρχεία wav είναι δυαδικά—δηλαδή τα περιεχόμενά τους δεν είναι άμεσα αναγνώσιμα ως\nκείμενο αλλά αντιθέτως περιέχουν μια σειρά από bytes διατεταγμένα σε ένα αρχείο στον δίσκο\nμε συγκεκριμένες ερμηνείες. Τα αρχεία wav που θα κληθούμε να διαχειριστούμε στα πλαίσια\nτης εργασίας έχουν την ακόλουθη δομή:\n\n```text\nFileHeader | SampleData | OtherData\n```\n\nΔηλαδή αποτελούνται από μια κεφαλίδα (FileHeader) που περιέχει πληροφορίες για το\nσυγκεκριμένο αρχείο ήχου wav, ακολουθούμενο από τα ίδια τα δείγματα του ήχου (SampleData)\nκαι στην συνέχεια ακολουθούν προαιρετικά άλλα δεδομένα (OtherData). Τα αρχεία κεφαλίδας\nwav, περιέχουν τα ακόλουθα πεδία με την σειρά:\n\n- 4 bytes με τους χαρακτήρες `RIFF` (αρχικά του Resource Interchange File Format, που είναι\n  το πρότυπο που χρησιμοποιείται για τη δομή των wav αρχείων).\n- 4 bytes, συμβολικά *SizeOfFile*, για το μέγεθος του αρχείου, που στην πραγματικότητα\n  είναι το πλήθος των bytes που ακολουθούν μέχρι το τέλος του αρχείου. Ουσιαστικά, είναι\n  το μέγεθος του αρχείου στον δίσκο μείον 8 bytes, δηλαδή αυτά που καταλαμβάνουν το\n  τρέχον πεδίο και το προηγούμενο (RIFF). Σημειώνεται ότι η αναπαράσταση ακεραίων χωρίς\n  πρόσημο γίνεται κατά σειρά από το λιγότερο σημαντικό byte προς το περισσότερο σημαντικό\n  (πρότυπο [little-endian](https://en.wikipedia.org/wiki/Endianness)). Δηλαδή, ο ακέραιος\n  `0xA3870FB9` αναπαρίσταται κατά σειρά με τα bytes `0xB9, 0x0F, 0x87, 0xA3`.\n- 4 bytes με τους χαρακτήρες `WAVE`, που υποδεικνύουν τη συγκεκριμένη υποκατηγορία\n  αρχείων που ακολουθούν το πρότυπο RIFF.\n- 4 bytes με τους χαρακτήρες `\"fmt \"` (προσοχή στον τελευταίο χαρακτήρα κενού\n  διαστήματος), που υποδεικνύουν την έναρξη του τμήματος format (format chunk) του\n  αρχείου.\n- 4 bytes για τον χώρο που καταλαμβάνουν τα δεδομένα του τμήματος format που θα\n  ακολουθήσουν. Στα αρχεία που θα χρησιμοποιηθούν στην εργασία, η τιμή αυτού του πεδίου\n  θα είναι πάντα 16 (`0x00000010`). Και εδώ εφαρμόζεται το πρότυπο little-endian, δηλαδή ο\n  αριθμός αυτός αποθηκεύεται με την ακολουθία από bytes `0x10, 0x00, 0x00, 0x00`.\n- 2 bytes για τον τύπο του WAVE format. Για την εργασία, αυτός θα ισούται πάντα με 1\n  (`0x0001`) και θα αποθηκεύεται κατά little-endian, δηλαδή με τα bytes `0x01, 0x00`.\n- 2 bytes, συμβολικά *MonoStereo*, για το αν ο ήχος είναι μονοφωνικός (τιμή `0x0001`) ή\n  στερεοφωνικός με δύο κανάλια (τιμή `0x0002`). Προσοχή στο little-endian, όπως και σε\n  όλες τις καταχωρήσεις ακεραίων που ακολουθούν.\n- 4 bytes, συμβολικά *SampleRate*, για το ρυθμό δειγματοληψίας, δηλαδή πόσες τιμές, ανά\n  δευτερόλεπτο, της συνάρτησης του αναλογικού ήχου έχουν καταγραφεί στο αρχείο.\n- 4 bytes, συμβολικά *BytesPerSec*, για το πλήθος bytes ανά δευτερόλεπτο ήχου, που είναι\n  καταχωρημένα στο αρχείο.\n- 2 bytes, συμβολικά *BlockAlign*, για το πλήθος των bytes που απαιτούνται για την\n  καταχώρηση της πληροφορίας του ήχου σε μία χρονική στιγμή, για όλα τα κανάλια.\n  Σημειώστε ότι πάντοτε θα πρέπει να ισχύει ότι *BytesPerSec = SampleRate × BlockAlign*.\n- 2 bytes, συμβολικά *BitsPerSample*, για το πλήθος των bits που απαιτούνται για την\n  καταχώρηση της πληροφορίας του ήχου σε μία χρονική στιγμή, για ένα μόνο κανάλι. Στα\n  πλαίσια της εργασίας, αυτή η τιμή θα είναι είτε 8 (`0x0008`), είτε 16 (`0x0010`). Για\n  *BitsPerSample* = 8, η ένταση του ήχου είναι ένας ακέραιος χωρίς πρόσημο στο διάστημα\n  [0,255], ενώ για *BitsPerSample* = 16, η ένταση του ήχου είναι ένας ακέραιος με πρόσημο\n  στο διάστημα [-32768,32767]. Σημειώστε ότι πάντοτε θα πρέπει να ισχύει ότι\n  *BlockAlign = BitsPerSample/8 × MonoStereo*.\n- 4 bytes με τους χαρακτήρες `data`, που υποδεικνύουν την έναρξη του τμήματος data (data\n  chunk) του αρχείου.\n- 4 bytes, συμβολικά *SizeOfData*, για τον χώρο που καταλαμβάνουν τα δεδομένα του\n  τμήματος data που θα ακολουθήσουν.\n\nΜετά την κεφαλίδα του αρχείου, ακολουθούν τα ψηφιοποιημένα δεδομένα του ήχου με χρονική\nσειρά (SampleData). Στην περίπτωση στερεοφωνικού ήχου με δύο κανάλια, για κάθε χρονική\nστιγμή, υπάρχει ένα ζευγάρι δεδομένων, με το πρώτο στοιχείο να αντιστοιχεί στο αριστερό\nκανάλι και το δεύτερο στοιχείο στο δεξιό κανάλι. Μετά το τέλος των δεδομένων ήχου,\nενδεχομένως να υπάρχουν και άλλα τμήματα (OtherData) που προβλέπονται για την κατηγορία\nWAVE, με τα οποία όμως δεν θα ασχοληθούμε στην εργασία.\n\nΑς δούμε τώρα τα περιεχόμενα ενός πραγματικού αρχείου wav. Μπορούμε να δούμε τα δυαδικά\nπεριεχόμενα οποιουδήποτε αρχείου χρησιμοποιώντας την εντολή `od` ως εξής (η εκφώνηση\nδείχνει και ένα σχήμα με τα ίδια bytes μέσω `xxd -g1`, όπου σημειώνονται τα πεδία):\n\n```text\n$ od -tx1 good.wav\n0000000 52 49 46 46 85 00 00 00 57 41 56 45 66 6d 74 20\n0000020 10 00 00 00 01 00 01 00 44 ac 00 00 88 58 01 00\n0000040 02 00 10 00 64 61 74 61 58 00 00 00 00 00 d4 07\n0000060 a1 0f 5e 17 04 1f 8a 26 ea 2d 1c 35 18 3c d7 42\n0000100 54 49 86 4f 69 55 f6 5a 27 60 f8 64 63 69 64 6d\n0000120 f7 70 18 74 c5 76 fa 78 b6 7a f6 7b b9 7c ff 7c\n0000140 c8 7c 12 7c e0 7a 33 79 0b 77 6c 74 58 71 d1 6d\n0000160 dd 69 7e 65 b8 60 92 5b 0f 56 36 50 0c 4a 97 43\n0000200 df 3c ea 35 45 78 74 72 61 44 61 74 61\n0000215\n```\n\n> **Σημείωση.** Πέρα από την εντολή `od`, υπάρχουν και άλλες εντολές όπως οι: (1) `xxd`,\n> (2) `hexdump`, (3) `hexedit` που προσφέρουν αντίστοιχες δυνατότητες σε Unix-like\n> συστήματα (Linux, MacOS, WSL κοκ). Για να *συγκρίνετε* δύο δυαδικά αρχεία, μπορείτε να\n> χρησιμοποιήσετε την εντολή `cmp` ή την εντολή `vbindiff`. Για περιβάλλοντα Windows,\n> υπάρχουν ελεύθερα διαθέσιμα προγράμματα που λειτουργούν παρόμοια (π.χ.\n> <https://mh-nexus.de/en/hxd/>).\n\nΦτάσαμε λοιπόν στο ζητούμενο αυτής της άσκησης: να υλοποιήσουμε ένα πρόγραμμα επεξεργασίας\nαρχείων wav με δυνατότητες αλλαγής και παραγωγής ήχου—όλα σε γλώσσα C!\n\n### Τεχνικές Προδιαγραφές\n\n- Repository Name: `progintro/hw1-<YourUsername>`\n- README Filepath: `soundwave/README.md`\n- Αρχείο C (Filepath): `soundwave/src/soundwave.c`\n- Το αρχείο C που θα υποβληθεί πρέπει να μεταγλωττίζεται χωρίς ειδοποιήσεις για λάθη και\n  με κωδικό επιστροφής (exit code) που να είναι 0. Συγκεκριμένα, το αρχείο σας **πρέπει**\n  να μπορεί να μεταγλωττιστεί επιτυχώς με την ακόλουθη εντολή σε ένα από τα μηχανήματα\n  του εργαστηρίου (linuxXY.di.uoa.gr):\n  `gcc -Ofast -Wall -Wextra -Werror -pedantic -o soundwave soundwave.c -lm`\n- Δύο αρχεία που να περιέχουν στοιχεία εισόδου και εξόδου διαφορετικά από αυτά της\n  άσκησης για την εντολή `./soundwave rate 2.0`. Συγκεκριμένα προτείνουμε να βάλετε έναν\n  συνδυασμό που θεωρείται ότι είναι δύσκολος να γίνει σωστός.\n  - input Filepath: `soundwave/test/input.wav`\n  - output Filepath: `soundwave/test/output.wav`\n- Όλα τα περιεχόμενα των αρχείων wav θα δίνονται στο πρόγραμμά σας μέσω της πρότυπης\n  εισόδου (stdin) και πρέπει να διαβάζονται με χρήση της συνάρτησης `getchar`. Δεν θα\n  γίνουν δεκτές υλοποιήσεις όπου χρησιμοποιήθηκε κάποια άλλη συνάρτηση εισόδου εκτός της\n  `getchar`.\n- Όλες οι υποεντολές σας πρέπει να επιστρέφουν κωδικό εξόδου (exit code) 0 όταν\n  ολοκλήρωσαν την επεξεργασία τους επιτυχώς - διαφορετικά πρέπει να επιστρέφουν με κωδικό\n  εξόδου 1.\n- Το πρόγραμμά σας θα πρέπει να υλοποιεί τις ακόλουθες 5 υποεντολές:\n  - `info`: για τύπωμα των στοιχείων του wav και έλεγχο ορθότητας.\n  - `rate`: για αλλαγή της ταχύτητας αναπαραγωγής (αντίστοιχο με το playback speed σε\n    streaming υπηρεσίες).\n  - `channel`: για επιλογή του καναλιού που θέλουμε.\n  - `volume`: για μετατροπή της έντασης του ήχου.\n  - `generate`: για παραγωγή ήχου.\n\n  Αναλυτικές προδιαγραφές για την κάθε υποεντολή δίνονται στην συνέχεια.\n- **Περιορισμοί Μνήμης**. Το πρόγραμμά σας πρέπει να χρησιμοποιεί λιγότερο από 8MB μνήμης\n  ανεξαρτήτως της εντολής ή αρχείου ήχου που δίνεται.\n- **Περιορισμοί Χρόνου**. Το πρόγραμμά σας πρέπει να μπορεί να διαχειρίζεται αρχεία των\n  10MB σε λιγότερο από 1 δευτερόλεπτο.\n- **Περιορισμοί Εισόδου**. Το πρόγραμμά σας πρέπει να μπορεί να διαχειρίζεται ακολουθίες\n  ήχου wav *οποιουδήποτε μεγέθους*. Το κάθε byte εισόδου θα μπορεί να διαβαστεί από την\n  πρότυπη είσοδο *μόνο μία φορά* (δεν θα είναι εφικτή η χρήση `fseek`) χρησιμοποιώντας\n  την γνωστή μας `getchar`.\n- Απαγορεύεται ρητά η χρήση δομών (structs) σε αυτήν την εργασία.\n\n### Η Υποεντολή info (40% της βαθμολογίας)\n\nΌταν το πρόγραμμά σας κληθεί με την υποεντολή `info` ως πρώτο όρισμα, δηλαδή ως\n`./soundwave info` θα πρέπει να ελέγχει αν τα δεδομένα που διαβάστηκαν ακολουθούν το\nπρότυπο wav που περιγράφηκε παραπάνω και να εκτυπώνει τις σχετικές πληροφορίες του ήχου\n(χωρίς τα δεδομένα αυτά καθεαυτά). Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ ./soundwave info < good.wav\nsize of file: 133\nsize of format chunk: 16\nWAVE type format: 1\nmono/stereo: 1\nsample rate: 44100\nbytes/sec: 88200\nblock alignment: 2\nbits/sample: 16\nsize of data chunk: 88\n$ ./soundwave info < 1MB.wav\nsize of file: 1073210\nsize of format chunk: 16\nWAVE type format: 1\nmono/stereo: 2\nsample rate: 8000\nbytes/sec: 32000\nblock alignment: 4\nbits/sample: 16\nsize of data chunk: 1072948\n$ ./soundwave info < 2MB.wav\nsize of file: 2146158\nsize of format chunk: 16\nWAVE type format: 1\nmono/stereo: 2\nsample rate: 16000\nbytes/sec: 64000\nblock alignment: 4\nbits/sample: 16\nsize of data chunk: 2145896\n$ ./soundwave info < 5MB.wav\nsize of file: 5226758\nsize of format chunk: 16\nWAVE type format: 1\nmono/stereo: 2\nsample rate: 44100\nbytes/sec: 176400\nblock alignment: 4\nbits/sample: 16\nsize of data chunk: 5226496\n$ ./soundwave info < 10MB.wav\nsize of file: 10406730\nsize of format chunk: 16\nWAVE type format: 1\nmono/stereo: 2\nsample rate: 44100\nbytes/sec: 176400\nblock alignment: 4\nbits/sample: 16\nsize of data chunk: 10406468\n```\n\nΌλα τα αρχεία που φαίνονται στα παραδείγματα της εκφώνησης της εργασίας μπορείτε να τα\nκατεβάσετε από το <https://github.com/progintro/wav>.\n\nΟι εκτυπώσεις του προγράμματός σας θα γίνονται κανονικά στην πρότυπη έξοδο, **εκτός** αν\nπαρουσιαστεί κάποιο σφάλμα (δείτε παρακάτω) οπότε και θα πρέπει να τυπώσετε στο πρότυπο\nρεύμα εξόδου σφάλματος (stderr / standard error). Για να τυπώσετε στο stderr, μπορείτε να\nχρησιμοποιήσετε την συνάρτηση `fprintf` με πρώτο όρισμα το `stderr` εξής:\n\n```c\nfprintf(stderr, <ίδια ακριβώς ορίσματα με αυτά της printf>);\n```\n\nΤο πρόγραμμά σας πρέπει να είναι σε θέση να καταλαβαίνει λάθη που υπάρχουν στα δεδομένα\nήχου που διαβάστηκαν και να σταματά στο πρώτο λάθος που βρίσκει εκτυπώνοντας το κατάλληλο\nδιαγνωστικό μήνυμα στο stderr. Παραδείγματα εκτέλεσης σε προβληματικά δεδομένα εισόδου\nείναι τα ακόλουθα:\n\n```text\n$ ./soundwave info < bad_riff.wav\nError! \"RIFF\" not found\n$ echo $?\n1\n$ ./soundwave info < bad_riff.wav 2> error.txt\n$ cat error.txt\nError! \"RIFF\" not found\n$ ./soundwave info < bad_wave.wav\nsize of file: 133\nError! \"WAVE\" not found\n$ ./soundwave info < bad_fmt.wav\nsize of file: 133\nError! \"fmt \" not found\n$ ./soundwave info < bad_sfc.wav\nsize of file: 133\nsize of format chunk: 18\nError! size of format chunk should be 16\n$ ./soundwave info < bad_wtf.wav\nsize of file: 133\nsize of format chunk: 16\nWAVE type format: 2\nError! WAVE type format should be 1\n$ ./soundwave info < bad_ms.wav\nsize of file: 133\nsize of format chunk: 16\nWAVE type format: 1\nmono/stereo: 3\nError! mono/stereo should be 1 or 2\n$ ./soundwave info < bad_bys.wav\nsize of file: 133\nsize of format chunk: 16\nWAVE type format: 1\nmono/stereo: 1\nsample rate: 44100\nbytes/sec: 88202\nblock alignment: 2\nError! bytes/second should be sample rate x block alignment\n$ ./soundwave info < bad_bis.wav\nsize of file: 133\nsize of format chunk: 16\nWAVE type format: 1\nmono/stereo: 1\nsample rate: 44100\nbytes/sec: 88200\nblock alignment: 2\nbits/sample: 32\nError! bits/sample should be 8 or 16\n$ ./soundwave info < bad_ba.wav\nsize of file: 133\nsize of format chunk: 16\nWAVE type format: 1\nmono/stereo: 2\nsample rate: 44100\nbytes/sec: 88200\nblock alignment: 2\nbits/sample: 16\nError! block alignment should be bits per sample / 8 x mono/stereo\n$ ./soundwave info < bad_data.wav\nsize of file: 133\nsize of format chunk: 16\nWAVE type format: 1\nmono/stereo: 1\nsample rate: 44100\nbytes/sec: 88200\nblock alignment: 2\nbits/sample: 16\nError! \"data\" not found\n$ ./soundwave info < bad_insfd.wav\nsize of file: 133\nsize of format chunk: 16\nWAVE type format: 1\nmono/stereo: 1\nsample rate: 44100\nbytes/sec: 88200\nblock alignment: 2\nbits/sample: 16\nsize of data chunk: 88\nError! insufficient data\n$ ./soundwave info < bad_sf.wav\nsize of file: 128\nsize of format chunk: 16\nWAVE type format: 1\nmono/stereo: 1\nsample rate: 44100\nbytes/sec: 88200\nblock alignment: 2\nbits/sample: 16\nsize of data chunk: 88\nError! bad file size (found data past the expected end of file)\n```\n\nΣτο τελευταίο παράδειγμα εκτέλεσης, παρατηρούμε ότι το `bad_sf.wav` αρχείο ισχυρίζεται ότι\nέχει μέγεθος 128 bytes (σύνολο 136 με τα αρχικά 8 bytes της κεφαλίδας), όμως αν ελέγξουμε\nτα συνολικά bytes του αρχείου:\n\n```text\n$ wc -c ./bad_sf.wav\n141 ./bad_sf.wav\n```\n\nπαρατηρούμε ότι έχει και άλλα bytes στο τέλος τα οποία δεν συμπεριλαμβάνονται στο\nSizeOfFile και επομένως δεν περνάει τον έλεγχο ορθότητας (validation). Αντίστοιχα, μπορείτε\nνα φτιάξετε και εσείς τα δικά σας παραδείγματα με λανθασμένα wav προκειμένου να ελέγξετε\nότι το πρόγραμμά σας τα αναγνωρίζει επιτυχώς.\n\n### Η υποεντολή rate (40% της βαθμολογίας)\n\nΤώρα που το πρόγραμμά μας μπορεί να αναγνωρίζει αρχεία wav, ήρθε η ώρα να προσθέσουμε την\nπρώτη sound-editing υποεντολή μας, την υποεντολή `rate`, της οποίας η σύνταξη είναι\n`./soundwave rate fp_rate`, όπου `fp_rate` είναι ένας αριθμός κινητής υποδιαστολής\n(`double`) που αντιστοιχεί στην επιτάχυνση που επιθυμούμε στον ρυθμό αναπαραγωγής. Η\nυποεντολή `rate`, εκτός από τον έλεγχο ορθότητας των δεδομένων εισόδου θέλουμε να μεταφέρει\nστην έξοδο, με τη βοήθεια της συνάρτησης `putchar`, τα δεδομένα του ήχου, έχοντας αλλάξει\nτην ταχύτητα αναπαραγωγής του, χωρίς να αλλοιώσει τα δείγματα που αποτελούν τον\nψηφιοποιημένο ήχο.\n\nΑν το υλοποιήσουμε σωστά, καλώντας το πρόγραμμά μας ως\n`./soundwave rate 0.5 < input.wav > output.wav` περιμένουμε το `output.wav` αρχείο να\nαναπαράγεται με υποδιπλάσιο ρυθμό, δηλαδή στον διπλάσιο χρόνο από τον αρχικό. Σκεφτείτε\nποιες παράμετροι των δεδομένων εισόδου θα πρέπει να αλλάξουν και πώς, ώστε να επιτευχθεί\nτο ζητούμενο. Σε κάθε περίπτωση, η έξοδος του προγράμματος πρέπει να είναι μία νόμιμη\nακολουθία από δεδομένα wav. Ακόμα και αν υπάρχουν στην είσοδο επιπλέον bytes μετά το τμήμα\nτων δεδομένων του (OtherData), θα πρέπει και αυτά να μεταφερθούν στην έξοδο, προφανώς\nαυτούσια. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ ./soundwave info < LaughEvil.wav\nsize of file: 329266\nsize of format chunk: 16\nWAVE type format: 1\nmono/stereo: 1\nsample rate: 44100\nbytes/sec: 88200\nblock alignment: 2\nbits/sample: 16\nsize of data chunk: 329230\n$ ./soundwave rate 0.5 < LaughEvil.wav > LaughEvil2.wav\n$ ./soundwave info < LaughEvil2.wav\nsize of file: 329266\nsize of format chunk: 16\nWAVE type format: 1\nmono/stereo: 1\nsample rate: 22050\nbytes/sec: 44100\nblock alignment: 2\nbits/sample: 16\nsize of data chunk: 329230\n$ ./soundwave rate 0.5 < ThePinkPantherTheme.wav > ThePinkPantherTheme2.wav\n$ ./soundwave rate 0.5 < la.wav > la2.wav\n$ ./soundwave rate 0.5 < 8bitstereo.wav > 8bitstereo2.wav\n```\n\nΣτα παραπάνω παραδείγματα, η έξοδος του προγράμματος ανακατευθύνεται σε ένα νέο αρχείο\nήχου. Για να τα ακούσετε, κάνετε διπλό κλικ στο αρχείο ή χρησιμοποιήστε μια εντολή όπως η\n`play` (Linux) ή η `afplay` (MacOS). Σε Linux μπορεί να αποφευχθεί η δημιουργία αρχείου\nμε σωλήνωση, για παράδειγμα για ένα απομακρυσμένο αρχείο ήχου:\n\n```text\ncurl -s https://raw.githubusercontent.com/progintro/wav/refs/heads/main/la.wav |\n  ./soundwave rate 0.5 | play -\n```\n\nΑντίστοιχα, μπορείτε να χρησιμοποιήσετε την παράμετρο της υποεντολής `rate` προκειμένου να\n*διπλασιάσετε* την ταχύτητα αναπαραγωγής του. Διπλασιάζοντας την ταχύτητα αναπαραγωγής (2x\nspeedup), ο χρόνος αναπαραγωγής θα υποδιπλασιασθεί, αφού τα δείγματα που αποτελούν τον\nψηφιοποιημένο ήχο θα πρέπει και πάλι να μεταφερθούν αναλλοίωτα. Παραδείγματα εκτέλεσης\nακολουθούν:\n\n```text\n$ ./soundwave info < LaughSarc.wav\nsize of file: 1541540\nsize of format chunk: 16\nWAVE type format: 1\nmono/stereo: 2\nsample rate: 48000\nbytes/sec: 192000\nblock alignment: 4\nbits/sample: 16\nsize of data chunk: 1541504\n$ ./soundwave rate 2 < LaughSarc.wav > LaughSarc3.wav\n$ ./soundwave info < LaughSarc3.wav\nsize of file: 1541540\nsize of format chunk: 16\nWAVE type format: 1\nmono/stereo: 2\nsample rate: 96000\nbytes/sec: 384000\nblock alignment: 4\nbits/sample: 16\nsize of data chunk: 1541504\n$ ./soundwave rate 2.0 < ThePinkPantherTheme.wav > ThePinkPantherTheme3.wav\n$ ./soundwave rate 2.0 < narc.wav > narc3.wav\n$ ./soundwave rate 2.0 < narc.wav | ./soundwave info\nsize of file: 4956196\nsize of format chunk: 16\nWAVE type format: 1\nmono/stereo: 2\nsample rate: 88200\nbytes/sec: 352800\nblock alignment: 4\nbits/sample: 16\nsize of data chunk: 4956160\n$ ./soundwave rate 2.0 < 8bitmono.wav | tee 8bitmono3.wav | ./soundwave info\nsize of file: 44136\nsize of format chunk: 16\nWAVE type format: 1\nmono/stereo: 1\nsample rate: 88200\nbytes/sec: 88200\nblock alignment: 1\nbits/sample: 8\nsize of data chunk: 44100\n```\n\n### Η υποεντολή channel (20% της βαθμολογίας)\n\nΗ υποεντολή `channel` επιτρέπει στον χρήστη να διαλέξει να αναπαράξει δεδομένα μόνο από το\nαριστερό ή δεξί κανάλι ήχου στην περίπτωση που ο ήχος της εισόδου είναι στερεοφωνικός. Η\nσύνταξη της εντολής είναι ως εξής: `./soundwave channel left` για να κρατήσει μόνο τα\nδεδομένα από το αριστερό κανάλι και `./soundwave channel right` για να κρατήσει μόνο τα\nδεδομένα από το δεξί κανάλι. Όπως προηγουμένως, το πρόγραμμά σας πρέπει να πραγματοποιεί\nέλεγχο ορθότητας των δεδομένων εισόδου και μεταφέρει στην έξοδο, με τη βοήθεια της\nσυνάρτησης `putchar`, τα δεδομένα μόνο του καναλιού του ήχου που ζήτησε ο χρήστης. Αν ο\nήχος στην είσοδο είναι μονοφωνικός, να μην προκύπτει σφάλμα, αλλά απλώς να μεταφέρεται στην\nέξοδο το μοναδικό κανάλι της εισόδου. Σκεφτείτε ποιες παράμετροι των δεδομένων εισόδου θα\nπρέπει να αλλάξουν και πώς και ποια από τα bytes του τμήματος δεδομένων της εισόδου θα\nπρέπει να μεταφερθούν στην έξοδο, ώστε να επιτευχθεί το ζητούμενο. Σε κάθε περίπτωση, η\nέξοδος του προγράμματος πρέπει να είναι μία νόμιμη ακολουθία από δεδομένα που συνιστούν\nέναν ήχο με βάση το πρότυπο που έχει περιγραφεί. Ακόμα και αν υπάρχουν στην είσοδο\nεπιπλέον bytes μετά το τμήμα των δεδομένων του (OtherData), θα πρέπει και αυτά να\nμεταφερθούν στην έξοδο, προφανώς αυτούσια. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ ./soundwave info < 8bitstereo.wav\nsize of file: 176436\nsize of format chunk: 16\nWAVE type format: 1\nmono/stereo: 2\nsample rate: 44100\nbytes/sec: 88200\nblock alignment: 2\nbits/sample: 8\nsize of data chunk: 176400\n$ ./soundwave channel left < 8bitstereo.wav | tee 8bitstereo4.wav | ./soundwave info\nsize of file: 88236\nsize of format chunk: 16\nWAVE type format: 1\nmono/stereo: 1\nsample rate: 44100\nbytes/sec: 44100\nblock alignment: 1\nbits/sample: 8\nsize of data chunk: 88200\n$ ./soundwave channel left < CaliforniaDreamin.wav > CaliforniaDreamin4.wav\n$ ./soundwave channel right < 8bitstereo.wav > 8bitstereo5.wav\n$ ./soundwave channel right < CaliforniaDreamin.wav > CaliforniaDreamin5.wav\n```\n\n### Η υποεντολή volume (Bonus 20% της βαθμολογίας)\n\nΗ υποεντολή `volume` δέχεται έναν πολλαπλασιαστή για την ένταση του ήχου με την σύνταξη\n`./soundwave volume fp_multiplier` και παράγει ένα καινούριο αρχείο ήχου όπου η ένταση κάθε\nδείγματος πολλαπλασιάζεται με το καινούριο volume: $\\mathrm{trunc}(original \\cdot fp\\_volume)$\n(όπου trunc ο τελεστής αποκοπής σε ακέραιο). Για παράδειγμα, αν το πρόγραμμά σας κληθεί ως\nεξής: `./soundwave volume 0.125` περιμένουμε ότι το αρχείο ήχου εξόδου θα έχει το 1/8 της\nέντασης του αρχικού αρχείου. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ ./soundwave volume 0.125 < 8bitmono.wav > 8bitmono6.wav\n$ ./soundwave volume 0.125 < 8bitstereo.wav > 8bitstereo6.wav\n$ ./soundwave volume 0.125 < la.wav | tee la6.wav | ./soundwave info\nsize of file: 88236\nsize of format chunk: 16\nWAVE type format: 1\nmono/stereo: 1\nsample rate: 44100\nbytes/sec: 88200\nblock alignment: 2\nbits/sample: 16\nsize of data chunk: 88200\n```\n\n### Η υποεντολή generate (Bonus 30% της βαθμολογίας)\n\nΟι παραπάνω εντολές επιτρέπουν στο πρόγραμμά μας να επεξεργάζεται υπάρχοντα αρχεία ήχου. Τι\nκάνουμε όμως αν εμείς θέλουμε να παράξουμε τους δικούς μας ήχους; Σε αυτό ακριβώς το\nπρόβλημα έρχεται να δώσει λύση η υποεντολή `generate`. Η σύνταξη της εντολής generate είναι\n`./soundwave generate` και παράγει στην έξοδο δεδομένα τύπου wav, με βάση τον εξής\nμαθηματικό τύπο (το $\\pi$ είναι το γνωστό 3.14… και με το sin συμβολίζεται η συνάρτηση του\nημιτόνου):\n\n$$f(t) = \\mathrm{trunc}(amp \\cdot \\sin(2\\pi f_c t - m_i \\cdot \\sin(2\\pi f_m t)))$$\n\nΓια το σκοπό αυτό, ορίστε μία συνάρτηση C με πρωτότυπο το\n\n```c\nvoid mysound(int dur, int sr, double fm, double fc, double mi, double amp);\n```\n\nη οποία να καλείται με κατάλληλες τιμές στα ορίσματά της από τη `main` συνάρτηση, ώστε να\nπαράγει τον κατάλληλο ήχο με βάση τον μαθηματικό τύπο που δόθηκε. Η υποεντολή, πέρα από\nτον βασικό τρόπο με τον οποίο καλείται (χωρίς άλλα ορίσματα) πρέπει να μπορεί να\nυποστηρίζει τα ακόλουθα προαιρετικά ορίσματα για τον καθορισμό των παραμέτρων:\n\n- `--dur int_duration`: Το όρισμα dur είναι η διάρκεια του ήχου σε δευτερόλεπτα (ακέραιος).\n  Default: 3.\n- `--sr int_sr`: Το sr είναι το *SampleRate* για την ψηφιοποίηση του ήχου (ακέραιος).\n  Default: 44100.\n- `--fm fp_fm`: Το frequency modulation που χρησιμοποιείται στο σήμα f(t) (κινητής\n  υποδιαστολής). Default: 2.0.\n- `--fc fp_fc`: Το carrier frequency που χρησιμοποιείται στο σήμα f(t) (κινητής\n  υποδιαστολής). Default: 1500.0.\n- `--mi fp_mi`: Το modulation index που χρησιμοποιείται στο σήμα f(t) (κινητής\n  υποδιαστολής). Default: 100.0.\n- `--amp fp_amp`: Το amplitude (δηλαδή η ένταση) που χρησιμοποιείται στο σήμα f(t)\n  (κινητής υποδιαστολής). Default: 30000.0.\n\nΟι παραπάνω παράμετροι πρέπει να τηρούνται πλήρως κατά την παραγωγή του ηχητικού σήματος.\nΓια το $\\pi$ μπορείτε να χρησιμοποιήσετε τη συμβολική σταθερά `M_PI`, που είναι ορισμένη\nστο `math.h`. Ο ήχος που θα παραχθεί να είναι μονοφωνικός (*MonoStereo* = 1) και να\nαναπαρίσταται με 2 bytes ανά δείγμα (*BitsPerSample* = 16). Καλέστε το πρόγραμμά σας με τις\ndefault παραμέτρους. Τι ήχος παράγεται; Ενδεικτική εκτέλεση:\n\n```text\n$ ./soundwave generate > mysound.wav\n$ ./soundwave info < mysound.wav\nsize of file: 264636\nsize of format chunk: 16\nWAVE type format: 1\nmono/stereo: 1\nsample rate: 44100\nbytes/sec: 88200\nblock alignment: 2\nbits/sample: 16\nsize of data chunk: 264600\n./soundwave generate --dur 5 --fm 1.2 --fc 300 --mi 100 --amp 15000 > space.wav\n```\n\n### Διαγωνισμός Δημιουργικότητας και Τελική Υποβολή\n\nΣας συνιστούμε να πειραματιστείτε και με άλλες δυνατότητες—για παράδειγμα την προσθήκη\nορισμάτων `--help` ώστε να μπορεί να βρούμε μια γρήγορη περιγραφή των διαφόρων δυνατοτήτων\nτου προγράμματός σας. Για να λάβετε συμμετοχή στον διαγωνισμό δημιουργικότητας στο τέλος\nτου εξαμήνου, μπορείτε να υλοποιήσετε μια δική σας υποεντολή `./soundwave dj` (με όποια\nορίσματα θέλετε) η οποία θα είναι σε θέση να παράξει ενδιαφέροντες και δημιουργικούς\nήχους! Αν κάποια υποβολή μας εκπλήξει, θα λάβει επιπλέον bonus μέχρι 50% της βαθμολογίας.\n\nΤέλος, πριν την υποβολή της εργασίας, μην ξεχάσετε το `soundwave/README.md`, μέσα στο οποίο\nπρέπει να συμπεριλάβετε τις όποιες παρατηρήσεις σας κατά την διεκπεραίωση της άσκησης. Ο\nκώδικας απαιτείται να είναι καλά τεκμηριωμένος με σχόλια καθώς αυτό θα είναι μέρος της\nβαθμολόγησης.",
  "hint": "Γράψε πρώτα βοηθητικές συναρτήσεις που διαβάζουν (και γράφουν) έναν ακέραιο 2 ή 4 bytes\nlittle-endian με `getchar`/`putchar`, συνθέτοντας τα bytes με ολισθήσεις και `|`, και έλεγξε\nπαντού για `EOF`. Επειδή δεν χωράει όλο το αρχείο στη μνήμη και δεν επιτρέπονται δομές,\nεπεξεργάσου τα δείγματα σε ροή, ένα-ένα, και σκέψου ποια πεδία της κεφαλίδας αλλάζουν σε\nκάθε υποεντολή (π.χ. στο `channel` αλλάζουν τα μεγέθη, όχι μόνο τα δείγματα). Πρόσεξε ότι\nτα δείγματα των 8 bits είναι χωρίς πρόσημο ενώ των 16 bits με πρόσημο, κάτι που μετράει\nστο `volume`, και ότι η `generate` πρέπει να ξέρει εκ των προτέρων το *SizeOfData* για να\nγράψει την κεφαλίδα."
 },
 {
  "id": "hw-2025-hw2-elevate",
  "kind": "homework",
  "title": "Ανελκυστήρες για Ανυπόμονους και Ανυπόμονες (elevate)",
  "source": {
   "title": "Εργασία 2 (2025-26), Άσκηση 1",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/hw2.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   25,
   11,
   23
  ],
  "topics": [
   "dynamic-programming",
   "recursion",
   "complexity",
   "dynamic-memory",
   "code-organization",
   "files"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α25.4",
  "path": "questions/homework/hw-2025-hw2-elevate.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2025-hw2-elevate.html",
  "statement": "Έχετε βρεθεί ποτέ να περιμένετε τον ανελκυστήρα να έρθει στον όροφό σας και να παίρνει\nυπερβολικά πολύ χρόνο; Σε αυτήν την άσκηση θα γράψουμε ένα πρόγραμμα-οδηγό (driver) που\nβελτιστοποιεί τις αποφάσεις ενός ανελκυστήρα, ώστε οι επιβάτες να περπατούν όσο το\nδυνατόν λιγότερους ορόφους.\n\n**Μοντελοποίηση του προβλήματος**. Έστω ότι ο ανελκυστήρας μας λειτουργεί σε ένα κτήριο με\nάπειρους ορόφους (όροφοι 1, 2, 3, ...). Στο ισόγειο (όροφος 0) βρίσκονται $numPeople$\nάνθρωποι, καθένας από τους οποίους θέλει να πάει στον όροφο $dests_i$\n($1 \\le i \\le numPeople$). Για κάποιους (τεχνικούς και άλλους λόγους—ο κατασκευαστής ήταν\nελαφρώς σφιχτοχέρης) ο ανελκυστήρας θα ξεκινήσει από το ισόγειο και θα κάνει *το πολύ*\n$numStops$ στάσεις. Κάθε επιβάτης θα βγει στον όροφο (κάποια από τις στάσεις του\nανελκυστήρα) που είναι πιο κοντά στον όροφο που είναι ο προορισμός του και θα πάει από τις\nσκάλες στον προορισμό του. Κάθε μετάβαση επιβάτη από τις σκάλες από όροφο σε γειτονικό του\nόροφο (είτε ανεβαίνοντας, είτε κατεβαίνοντας) έχει κόστος 1. Ποια είναι η βέλτιστη λύση\n(συνολικό ελάχιστο κόστος), δηλαδή ποιες στάσεις πρέπει να κάνει ο ανελκυστήρας, ώστε οι\nεπιβάτες του να κάνουν τις λιγότερες δυνατές μετακινήσεις με τα πόδια; Μεταξύ λύσεων με το\nίδιο κόστος, προτιμώνται εκείνες που ο ανελκυστήρας σταματά σε χαμηλότερους ορόφους. Να\nσημειωθεί ότι δεν είναι απαραίτητο όλοι οι επιβάτες να μπουν στον ανελκυστήρα. Κάποιοι\nμπορεί να πάνε με τα πόδια από το ισόγειο στον προορισμό τους (επειδή αυτός θα είναι πιο\nκοντά στο ισόγειο απ' ότι στην πρώτη στάση του ανελκυστήρα). Επίσης, υπάρχει ενδεχόμενο να\nυπάρχει λύση στο πρόβλημα με λιγότερες από $numStops$ στάσεις, επειδή ο ανελκυστήρας θα\nσταματήσει σε όλους τους προορισμούς των επιβατών του και το κόστος θα ισούται με 0.\n\nΑς δούμε λοιπόν ένα παράδειγμα. Έστω $numPeople = 5$, $numStops = 2$ και\n$dests = [11\\ 2\\ 7\\ 13\\ 7]$. Αν ο ανελκυστήρας κάνει τις δύο στάσεις του στους ορόφους\n$stops = [5\\ 12]$, τότε ο πρώτος επιβάτης με προορισμό τον όροφο 11 θα βγει στον όροφο 12\n(πλησιέστερη στάση στον προορισμό του) και θα κατέβει με τις σκάλες 1 όροφο (κόστος 1). Ο\nδεύτερος επιβάτης με προορισμό τον όροφο 2 δεν θα μπει στον ανελκυστήρα και θα ανέβει δύο\nορόφους με τις σκάλες (κόστος 2). Για τον τρίτο επιβάτη, έχουμε κόστος ίσο με 2 (προορισμός\nο όροφος 7 και στάση ο όροφος 5). Με όμοιο τρόπο, βρίσκουμε ότι το κόστος για τον τέταρτο\nεπιβάτη είναι 1 και για τον πέμπτο είναι 2. Το συνολικό κόστος ισούται με\n$1 + 2 + 2 + 1 + 2 = 8$. Όμως, η λύση $stops = [7\\ 11]$ έχει κόστος ίσο με 4 (γιατί;) και\nμπορεί να αποδειχθεί ότι είναι η βέλτιστη λύση.\n\n**Σκέψεις για την επίλυση του προβλήματος**. Δεν υπάρχει περίπτωση η βέλτιστη λύση να\nπεριέχει στάση σε όροφο μεγαλύτερο από τον υψηλότερο προορισμό των επιβατών (αν υπήρχε\nτέτοια στάση, θα μπορούσαμε να την μεταφέρουμε σε αυτόν τον όροφο και η νέα λύση σίγουρα θα\nέχει μικρότερο κόστος). Για τη συνέχεια, ας συμβολίσουμε τον υψηλότερο προορισμό των\nεπιβατών ως $numFloors$.\n\nΗ διαχείριση του ενδεχομένου να αρκούν λιγότερες στάσεις από $numStops$, οπότε έχουμε λύση\nελαχίστου κόστους ίσου με 0, μπορεί να γίνει με απλό τρόπο. Σκεφτείτε την περίπτωση\n$numPeople = 5$, $numStops = 3$ και $dests = [6\\ 6\\ 6\\ 6\\ 6]$. Αρκεί ο ανελκυστήρας να κάνει\nμόνο μία στάση, στον όροφο 6 (κόστος 0). Την λύση αυτή θα μπορούσαμε να την\nαναπαραστήσουμε σαν $stops = [0\\ 0\\ 6]$. Δηλαδή, θεωρούμε ότι υπάρχουν και επιπλέον,\nπρακτικά ανύπαρκτες, στάσεις στο ισόγειο.\n\nΑν $a$ και $b$ είναι δύο διαδοχικές στάσεις του ανελκυστήρα, ας θεωρήσουμε ότι με\n$fw(a, b)$ (τα αρχικά για τις λέξεις Floors Walked) συμβολίζουμε το συνολικό πλήθος των\nορόφων που θα χρειαστεί να περπατήσουν όλοι οι επιβάτες που έχουν προορισμό όροφο $d$ πιο\nψηλά από τον όροφο $a$ ($a < d$) και το πολύ μέχρι τον όροφο $b$ ($d \\le b$) για να πάνε\nστον όροφο $d$ από τις σκάλες, βγαίνοντας από τον ανελκυστήρα στον όροφο $a$ ή στον όροφο\n$b$, ανάλογα με το ποιος είναι κοντινότερος στον $d$. Το $b$ μπορεί να ισούται με $\\infty$,\nστην περίπτωση που ο όροφος $a$ είναι ο τελευταίος που θα σταματήσει ο ανελκυστήρας.\nΕπίσης, το $a$ μπορεί να ισούται με 0, στην περίπτωση που το $b$ είναι η πρώτη στάση του\nανελκυστήρα.\n\nΈστω $M_{i,j}$ το ελάχιστο κόστος για να εξυπηρετηθούν όλοι οι επιβάτες με $i$ ακριβώς\nστάσεις του ανελκυστήρα, η υψηλότερη από τις οποίες είναι στον όροφο $j$. Εκφράζεται από\nτην ακόλουθη αναδρομική σχέση:\n\n$$\n\\begin{aligned}\nM_{0,j} &= fw(0,\\infty), \\quad 0 \\le j \\le numFloors\\\\\nM_{i,j} &= \\min_{k=0}^{j}\\{M_{i-1,k} - fw(k,\\infty) + fw(k,j) + fw(j,\\infty)\\},\\\\\n&\\quad \\text{where } 1 \\le i \\le numStops,\\ 0 \\le j \\le numFloors\n\\end{aligned}\n$$\n\nΑν ο ανελκυστήρας δεν κινηθεί καθόλου ($i = 0$ στάσεις), όλοι οι επιβάτες θα πάνε στους\nπροορισμούς τους από τις σκάλες. Όταν προστεθεί μία επιπλέον στάση στον όροφο $j$ μετά από\nκάποια στον όροφο $k$, αλλάζει μόνο το κόστος των επιβατών με προορισμούς ψηλότερα από τον\nόροφο $k$: από το $M_{i-1,k}$ αφαιρούμε το κόστος τους με τις σκάλες από τον $k$ και το\nαντικαθιστούμε με το κόστος όσων έχουν προορισμό μέχρι τον $j$ (ανάμεσα σε $k$ και $j$)\nσυν το κόστος όσων έχουν προορισμό πάνω από τον $j$. Το ελάχιστο από αυτά τα κόστη, για όλα\nτα πιθανά $k$, είναι το $M_{i,j}$. Τελικά, το ελάχιστο κόστος για το πλήρες πρόβλημα ισούται\nμε\n\n$$MinCost = \\min_{j=0}^{numFloors}\\{M_{numStops,j}\\}$$\n\nκαι η τελευταία στάση του ανελκυστήρα είναι εκείνο το $j$ για το οποίο έχουμε το ελάχιστο\nστον προηγούμενο τύπο.\n\nΣτην εργασία αυτή λοιπόν, καλείστε να υλοποιήσετε ένα πρόγραμμα σε γλώσσα C το οποίο να\nβρίσκει αποδοτικά την βέλτιστη από πλευράς κόστους λειτουργίας του ανελκυστήρα. Καθώς δεν\nγνωρίζουμε εξ αρχής ποια λύση θα έχει καλύτερη απόδοση, θέλουμε να δοκιμάσετε τέσσερις (4)\nεναλλακτικές μεθόδους έτσι ώστε να μπορέσουμε να συγκρίνουμε τις επιδόσεις τους\n(benchmarking) και να επιλέξουμε την καλύτερη για χρήση σε συστήματα παραγωγής.\n\n### Τεχνικές Προδιαγραφές\n\n- Repository Name: `progintro/hw2-<YourUsername>`\n- README Filepath: `elevate/README.md`\n- Αρχεία C και headerfiles (Filepaths):\n  - `elevate/src/elevate.c` : το αρχείο που θα περιέχει την `main` σας.\n  - `elevate/src/recurse.c` : το αρχείο με την αναδρομική υλοποίηση\n  - `elevate/src/brute.c` : το αρχείο με την υλοποίηση ωμής βίας\n  - `elevate/src/memoize.c` : το αρχείο με την υλοποίηση που χρησιμοποιεί memoization\n  - `elevate/src/dp.c` : το αρχείο με την υλοποίηση που χρησιμοποιεί δυναμικό\n    προγραμματισμό\n  - `elevate/src/elevate.h` : το αρχείο κεφαλίδας με τους ορισμούς προτύπων συναρτήσεων\n    όπου απαιτείται.\n- Τα αρχεία C που θα υποβληθούν πρέπει να μεταγλωττίζονται χωρίς ειδοποιήσεις για λάθη και\n  με κωδικό επιστροφής (exit code) που να είναι 0. Συγκεκριμένα, το πρόγραμμά σας\n  **πρέπει** να μπορεί να μεταγλωττιστεί επιτυχώς με τις ακόλουθες εντολές σε ένα από τα\n  μηχανήματα του εργαστηρίου (linuxXY.di.uoa.gr):\n\n  ```text\n  gcc -Os -c -Wall -Wextra -Werror -pedantic recurse.c\n  gcc -Os -c -Wall -Wextra -Werror -pedantic brute.c\n  gcc -Os -c -Wall -Wextra -Werror -pedantic memoize.c\n  gcc -Os -c -Wall -Wextra -Werror -pedantic dp.c\n  gcc -Os -c -Wall -Wextra -Werror -pedantic elevate.c\n  gcc -Os -o elevate recurse.o brute.o memoize.o dp.o elevate.o\n  ```\n\n- Το πρόγραμμά σας θα πρέπει να παίρνει δύο ορίσματα από την γραμμή εντολών:\n  1. Το πρώτο υποχρεωτικό όρισμα θα είναι το όνομα του αρχείου εισόδου. Το αρχείο, θα\n     περιέχει τα δεδομένα του προβλήματος, δηλαδή τον αριθμό των ατόμων (numPeople), τον\n     αριθμό των στάσεων (numStops) καθώς και τις στάσεις που θέλουν να σταματήσουν τα άτομα\n     ($dests_i$) όπου $1 \\le i \\le numPeople$.\n  2. Το δεύτερο όρισμα θα έχει την μορφή `--mode=MODE` όπου ο χρήστης θα επιλέγει ποια\n     εναλλακτική υλοποίηση (MODE) επιθυμεί ανάμεσα στις ακόλουθες επιλογές: (1) `recurse`,\n     (2) `brute`, (3) `memoize`, (4) `dp`. Αφού ολοκληρώσετε την υλοποίησή σας, μπορείτε να\n     μετατρέψετε αυτό το όρισμα σε προαιρετικό έτσι ώστε να χρησιμοποιεί την βέλτιστη λύση\n     όταν ο χρήστης δεν το προσδιορίσει (default behavior).\n- Το πρόγραμμά σας πρέπει να χρησιμοποιεί την πρότυπη έξοδο για να τυπώσει τα\n  αποτελέσματά του: την τελευταία στάση που θα κάνει ο ανελκυστήρας καθώς και το ελάχιστο\n  κόστος σε αυτήν την περίπτωση.\n- Το πρόγραμμά σας πρέπει να επιστρέφει κωδικό εξόδου (exit code) 0 όταν ολοκληρώσει τον\n  υπολογισμό του επιτυχώς - διαφορετικά πρέπει να επιστρέφει με κωδικό εξόδου 1.\n\n#### Αναδρομική μέθοδος `--mode=recurse` (10%)\n\nΣτο αρχείο `recurse.c` θέλουμε να γράψετε μια λύση στο πρόβλημα με αναδρομικό τρόπο\nβασισμένη στην Σχέση που δόθηκε στην περιγραφή του προβλήματος. Η διεπαφή (interface) της\nλύσης είναι πάνω σε εσάς, αλλά θέλουμε υποχρεωτικά η υλοποίησή σας στο `recurse.c` να\nκαλείται από την `main` που θα βρίσκεται στο `elevate.c`. Στο πρόγραμμά σας δεν επιτρέπεται\nνα ορίσετε άλλον πίνακα εκτός από αυτόν που χρειάζεται για τη φύλαξη των προορισμών των\nεπιβατών. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ cat input1.txt\n5 2\n11 2 7 13 7\n$ ./elevate input1.txt --mode=recurse\nLast stop at floor: 11\nThe minimum cost is: 4\n$ cat input2.txt\n7 3\n8 10 3 8 12 6 5\n$ ./elevate input2.txt --mode=recurse\nLast stop at floor: 10\nThe minimum cost is: 5\n$ cat input3.txt\n6 4\n5 3 3 5 5 3\n$ ./elevate input3.txt --mode=recurse\nLast stop at floor: 5\nThe minimum cost is: 0\n$ cat input4.txt\n5 0\n1 2 3 4 5\n$ ./elevate input4.txt --mode=recurse\nNo lift stops\nThe minimum cost is: 15\n$ cat input5.txt\n20 4\n8 32 14 14 6 7 25 43 12 9 1 28 27 25 33 38 42 27 14 44\n$ time ./elevate input5.txt --mode=recurse\nLast stop at floor: 42\nThe minimum cost is: 30\n0.515u 0.003s 0:13.29 3.8%      0+0k 0+0io 0pf+0w\n$ cat input6.txt\n20 5\n8 32 14 14 6 7 25 43 12 9 1 28 27 25 33 38 42 27 14 44\n$ time ./elevate input6.txt --mode=recurse\nLast stop at floor: 42\nThe minimum cost is: 20\n4.318u 0.000s 0:14.74 29.2%     0+0k 0+0io 0pf+0w\n$ cat input7.txt\n20 6\n8 32 14 14 6 7 25 43 12 9 1 28 27 25 33 38 42 27 14 44\n$ time ./elevate input7.txt --mode=recurse\nLast stop at floor: 43\nThe minimum cost is: 15\n31.997u 0.000s 0:38.59 82.8%    0+0k 0+0io 0pf+0w\n$ cat input8.txt\n25 7\n1 2 2 3 5 6 6 8 10 13 15 15 16 17 18 18 18 20 22 25 30 38 49 55 62\n$ time ./elevate input8.txt --mode=recurse\nLast stop at floor: 62\nThe minimum cost is: 35\n3253.247u 0.003s 54:26.76 99.5% 0+0k 0+0io 0pf+0w\n```\n\n#### Μέθοδος \"ωμής βίας\" `--mode=brute` (30%)\n\nΠαρατηρήστε ότι στις τελευταίες ενδεικτικές εκτελέσεις της αναδρομικής μεθόδου, ο χρόνος\nαυξάνει δραματικά. Μία εντελώς διαφορετική μέθοδος για να προσεγγιστεί το πρόβλημα, η οποία\nδεν βασίζεται στην αναδρομική σχέση που δόθηκε, είναι να κατασκευάζονται συστηματικά όλες\nοι πιθανές λύσεις, δηλαδή οι δυνατοί συνδυασμοί στάσεων του ανελκυστήρα (brute force), για\nκάθε μία από αυτές να υπολογίζεται το κόστος της και, τελικά, σαν λύση να δοθεί αυτή που\nέχει το ελάχιστο κόστος. Αν ο μέγιστος αριθμός στάσεων είναι $numStops$, θα πρέπει να\nεξετασθούν όλες οι πιθανές λύσεις με 1 στάση, 2 στάσεις, κοκ., $numStops$ στάσεις.\nΥπενθυμίζεται ότι έχει νόημα να συζητάμε για στάσεις από 1 μέχρι $numFloors$. Η υλοποίησή\nσας πρέπει να γίνει εξ ολοκλήρου στο `brute.c` και να καλείται και πάλι από την `main`\nεντός του `elevate.c`. Ενδεικτικές εκτελέσεις ακολουθούν:\n\n```text\n$ ./elevate input1.txt --mode=brute\nLift stops are: 7 11\nThe minimum cost is: 4\n$\n$ ./elevate input2.txt --mode=brute\nLift stops are: 5 8 10\nThe minimum cost is: 5\n$\n$ ./elevate input3.txt --mode=brute\nLift stops are: 3 5\nThe minimum cost is: 0\n$\n$ ./elevate input4.txt --mode=brute\nNo lift stops\nThe minimum cost is: 15\n$\n$ time ./elevate input5.txt --mode=brute\nLift stops are: 7 14 27 42\nThe minimum cost is: 30\n0.035u 0.003s 0:02.39 1.2%      0+0k 0+0io 0pf+0w\n$\n$ time ./elevate input6.txt --mode=brute\nLift stops are: 7 14 27 32 42\nThe minimum cost is: 20\n0.240u 0.003s 0:02.87 8.3%      0+0k 0+0io 0pf+0w\n$\n$ time ./elevate input7.txt --mode=brute\nLift stops are: 7 14 27 32 38 43\nThe minimum cost is: 15\n1.732u 0.003s 0:04.15 41.6%     0+0k 0+0io 0pf+0w\n$\n$ time ./elevate input8.txt --mode=brute\nLift stops are: 6 15 18 25 38 49 62\nThe minimum cost is: 35\n118.186u 0.000s 2:00.45 98.1%   0+0k 0+0io 0pf+0w\n```\n\n#### Αναδρομή με απομνημόνευση `--mode=memoize` (20%)\n\nΠαρότι με την προηγούμενη εκδοχή βελτιώθηκαν σημαντικά οι χρόνοι εκτέλεσης, όταν το μέγεθος\nτης εισόδου μεγαλώνει αρκετά, η χρονική απόδοση του προγράμματος δεν είναι καλή, αφού\nελέγχουμε εξαντλητικά όλες τις πιθανές λύσεις, το πλήθος των οποίων αυξάνει εκθετικά με το\nπλήθος των ορόφων στους οποίους είναι πιθανό να γίνουν στάσεις.\n\nΟπότε, ας επιστρέψουμε στην αναδρομική μέθοδο. Γιατί όμως η αναδρομική μέθοδος έχει\nιδιαίτερα μεγάλους χρόνους εκτέλεσης για μεγάλες εισόδους; Μπορούμε να δούμε ότι\nεφαρμόζοντας την αναδρομική σχέση που δόθηκε, τα περισσότερα $M_{ij}$ υπολογίζονται\nπερισσότερες από μία φορά το καθένα, αρκετά από αυτά υπερβολικά μεγάλο αριθμό φορών. Πώς θα\nμπορούσαμε να το διορθώσουμε; Αρκεί να χρησιμοποιήσουμε ένα δισδιάστατο πίνακα στον οποίο\nνα αποθηκεύεται κάθε $M_{ij}$ την πρώτη φορά που υπολογίζεται και όταν χρειάζεται πάλι, να\nμην επαναϋπολογίζεται, αλλά να λαμβάνεται η τιμή του από τον πίνακα. Η λογική της\nβελτιωμένης μεθόδου εξακολουθεί να είναι αναδρομική, απλώς κάθε $M_{ij}$ υπολογίζεται\nακριβώς μία φορά. Αυτή η τεχνική λέγεται απομνημόνευση—*memoization* στα αγγλικά (προσοχή\n*όχι* memorization). Υλοποιήστε αυτήν την μέθοδο στο αρχείο `memoize.c` και ως συνήθως\nκαλέστε την από την `main` όταν δοθεί το κατάλληλο όρισμα από την γραμμή εντολών.\nΕνδεικτικές εκτελέσεις ακολουθούν:\n\n```text\n$ ./elevate input1.txt --mode=memoize\nLast stop at floor: 11\nThe minimum cost is: 4\n$\n$ ./elevate input2.txt --mode=memoize\nLast stop at floor: 10\nThe minimum cost is: 5\n$\n$ ./elevate input3.txt --mode=memoize\nLast stop at floor: 5\nThe minimum cost is: 0\n$\n$ ./elevate input4.txt --mode=memoize\nNo lift stops\nThe minimum cost is: 15\n$\n$ time ./elevate input5.txt --mode=memoize\nLast stop at floor: 42\nThe minimum cost is: 30\n0.006u 0.000s 0:02.37 0.0%      0+0k 0+0io 0pf+0w\n$\n$ time ./elevate input6.txt --mode=memoize\nLast stop at floor: 42\nThe minimum cost is: 20\n0.006u 0.000s 0:01.88 0.0%      0+0k 0+0io 0pf+0w\n$\n$ time ./elevate input7.txt --mode=memoize\nLast stop at floor: 43\nThe minimum cost is: 15\n0.007u 0.000s 0:02.05 0.0%      0+0k 0+0io 0pf+0w\n$\n$ time ./elevate input8.txt --mode=memoize\nLast stop at floor: 62\nThe minimum cost is: 35\n0.007u 0.003s 0:02.32 0.0%      0+0k 0+0io 0pf+0w\n```\n\n#### Δυναμικός Προγραμματισμός `--mode=dp` (40%)\n\nΣτην αναδρομική μέθοδο με απομνημόνευση, η λογική του υπολογισμού των $M_{ij}$ είναι με\nσειρά *από-επάνω-προς-τα-κάτω* (top-down), δηλαδή αρχίζουμε από τα μεγάλα $i$, οπότε\nαπαιτείται ο υπολογισμός των τιμών για μικρότερα $i$, κοκ., μέχρι να φτάσουμε στο $i = 0$.\nΜία αντίστροφη λογική είναι να συμπληρωθεί ο πίνακας των $M_{ij}$ με σειρά\n*από-κάτω-προς-τα-επάνω* (bottom-up): αρχίζουμε τους υπολογισμούς για $i = 0$, συνεχίζουμε\nμε $i = 1$ και τελικά καταλήγουμε στους υπολογισμούς για $i = numStops$. Η προσέγγιση αυτή\nχαρακτηρίζεται στη βιβλιογραφία ως *δυναμικός προγραμματισμός* (dynamic programming) και\nείναι από τις πιο συχνά χρησιμοποιούμενες τεχνικές βελτιστοποίησης. Χρησιμοποιώντας δυναμικό\nπρογραμματισμό, υλοποιήστε στο αρχείο `dp.c` την εύρεση της βέλτιστης λύσης. Όταν δίνεται\nτο επιπλέον όρισμα `--debug`, θέλουμε η λύση σας να εκτυπώνει και τις τιμές $M_{ij}$, μία\nγραμμή για κάθε $i$ (από 0 έως $numStops$) καθώς και όλες τις στάσεις του για την βέλτιστη\nλύση! Σκεφτείτε πώς θα μπορούσε να γίνει αυτό. Αρκούν οι τιμές $M_{ij}$; Μάλλον όχι. Μία\nιδέα, όχι όμως δεσμευτική, είναι να χρησιμοποιηθεί και ένας δεύτερος δισδιάστατος πίνακας,\nστον οποίο να φυλάσσεται για κάθε $(i, j)$ η τιμή του $k$ για την οποία στη στάση $i - 1$\nβρέθηκε η ελάχιστη τιμή για το $M(i, j)$, σύμφωνα με την αναδρομική σχέση που δόθηκε\nαρχικά. Θα πρέπει να σκεφτείτε, βέβαια, πώς θα εκμεταλλευτείτε τα περιεχόμενα αυτού του\nεπιπλέον πίνακα για να βρείτε τις στάσεις του ανελκυστήρα. Ενδεικτικές εκτελέσεις\nακολουθούν (στην εκφώνηση οι μεγάλες γραμμές αναδιπλώνονται· εδώ κάθε γραμμή $M_{i,\\cdot}$\nείναι σε μία γραμμή):\n\n```text\n$ ./elevate input1.txt --mode=dp --debug\n40 40 40 40 40 40 40 40 40 40 40 40 40 40\n40 35 30 27 24 20 16 12 12 12 12 12 14 16\n40 35 30 26 22 18 14 10 10  8  6  4  4  4\nLift stops are: 7 11\nThe minimum cost is: 4\n$\n$ ./elevate input2.txt --mode=dp --debug\n52 52 52 52 52 52 52 52 52 52 52 52 52\n52 45 38 31 26 21 18 16 14 16 18 21 24\n52 45 38 31 25 19 15 13  9  9  9 10 10\n52 45 38 31 25 19 14 11  7  7  5  5  5\nLift stops are: 5 8 10\nThe minimum cost is: 5\n$\n$ ./elevate input3.txt --mode=dp --debug\n24 24 24 24 24 24\n24 18 12  6  6  6\n24 18 12  6  3  0\n24 18 12  6  3  0\n24 18 12  6  3  0\nLift stops are: 3 5\nThe minimum cost is: 0\n$\n$ ./elevate input4.txt --mode=dp --debug\n15 15 15 15 15 15\nNo lift stops\nThe minimum cost is: 15\n$\n$ time ./elevate input5.txt --mode=dp --debug\n449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449\n449 429 411 392 373 354 335 318 303 290 279 268 257 247 237 232 227 221 215 208 201 194 187 180 173 165 161 157 157 156 155 154 153 154 157 160 163 166 169 174 179 184 189 196 205\n449 429 410 391 372 353 334 317 301 286 272 258 243 230 217 210 203 195 187 179 169 158 147 136 125 114 107 100  97  96  95  94  93  94  97 100 103 106 107 109 108 107 105 105 107\n449 429 410 391 372 353 334 316 300 285 271 256 241 228 215 206 195 184 173 162 151 140 129 118 107  96  89  82  79  78  77  76  70  66  64  62  60  58  55  54  52  50  48  48  50\n449 429 410 391 372 353 334 316 299 284 270 255 240 227 213 204 193 182 171 160 149 138 127 116 105  94  87  78  73  70  64  58  52  48  46  44  42  40  37  36  34  32  30  30  32\nLift stops are: 7 14 27 42\nThe minimum cost is: 30\n0.003u 0.003s 0:02.28 0.0%      0+0k 0+0io 0pf+0w\n$\n$ time ./elevate input6.txt --mode=dp --debug\n449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449\n449 429 411 392 373 354 335 318 303 290 279 268 257 247 237 232 227 221 215 208 201 194 187 180 173 165 161 157 157 156 155 154 153 154 157 160 163 166 169 174 179 184 189 196 205\n449 429 410 391 372 353 334 317 301 286 272 258 243 230 217 210 203 195 187 179 169 158 147 136 125 114 107 100  97  96  95  94  93  94  97 100 103 106 107 109 108 107 105 105 107\n449 429 410 391 372 353 334 316 300 285 271 256 241 228 215 206 195 184 173 162 151 140 129 118 107  96  89  82  79  78  77  76  70  66  64  62  60  58  55  54  52  50  48  48  50\n449 429 410 391 372 353 334 316 299 284 270 255 240 227 213 204 193 182 171 160 149 138 127 116 105  94  87  78  73  70  64  58  52  48  46  44  42  40  37  36  34  32  30  30  32\n449 429 410 391 372 353 334 316 299 283 269 254 239 226 212 202 191 180 169 158 147 136 125 114 103  92  85  76  71  66  60  54  48  44  42  40  36  32  28  26  24  22  20  20  21\nLift stops are: 7 14 27 32 42\nThe minimum cost is: 20\n0.006u 0.000s 0:02.01 0.0%      0+0k 0+0io 0pf+0w\n$\n$ time ./elevate input7.txt --mode=dp --debug\n449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449 449\n449 429 411 392 373 354 335 318 303 290 279 268 257 247 237 232 227 221 215 208 201 194 187 180 173 165 161 157 157 156 155 154 153 154 157 160 163 166 169 174 179 184 189 196 205\n449 429 410 391 372 353 334 317 301 286 272 258 243 230 217 210 203 195 187 179 169 158 147 136 125 114 107 100  97  96  95  94  93  94  97 100 103 106 107 109 108 107 105 105 107\n449 429 410 391 372 353 334 316 300 285 271 256 241 228 215 206 195 184 173 162 151 140 129 118 107  96  89  82  79  78  77  76  70  66  64  62  60  58  55  54  52  50  48  48  50\n449 429 410 391 372 353 334 316 299 284 270 255 240 227 213 204 193 182 171 160 149 138 127 116 105  94  87  78  73  70  64  58  52  48  46  44  42  40  37  36  34  32  30  30  32\n449 429 410 391 372 353 334 316 299 283 269 254 239 226 212 202 191 180 169 158 147 136 125 114 103  92  85  76  71  66  60  54  48  44  42  40  36  32  28  26  24  22  20  20  21\n449 429 410 391 372 353 334 316 299 283 268 253 238 225 211 201 190 179 168 157 146 135 124 113 102  91  83  74  69  64  58  52  46  42  40  36  32  28  24  22  20  18  16  15  16\nLift stops are: 7 14 27 32 38 43\nThe minimum cost is: 15\n0.007u 0.000s 0:02.02 0.0%      0+0k 0+0io 0pf+0w\n$\n$ time ./elevate input8.txt --mode=dp --debug\n474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474 474\n474 449 426 406 388 368 350 335 320 307 294 282 270 256 244 232 224 217 212 213 214 216 218 222 226 230 236 241 246 251 256 261 266 270 274 277 280 280 280 282 284 285 286 287 288 288 288 288 288 288 290 291 292 293 294 295 298 301 304 307 310 312 314\n474 449 425 404 384 363 344 329 314 298 282 267 252 237 224 210 200 192 186 186 186 186 180 176 172 167 164 161 157 153 149 147 145 143 140 137 134 131 128 127 126 125 124 122 120 118 116 114 112 110 110 110 110 110 110 110 112 114 116 117 118 119 120\n474 449 425 403 383 362 343 326 308 292 276 261 246 231 218 204 194 186 176 172 167 162 156 152 147 142 139 136 132 128 124 122 120 117 114 111 108 105 102 101 100  99  98  96  94  92  90  88  86  84  84  84  84  84  84  84  86  88  89  90  91  92  93\n474 449 425 403 382 361 342 325 307 291 274 259 244 228 214 200 190 180 170 166 160 154 148 143 138 133 130 126 122 118 114 112 110 107 104 101  98  94  90  88  86  84  82  80  78  76  74  72  70  67  66  65  64  63  62  61  62  63  64  65  66  67  68\n474 449 425 403 382 361 341 324 306 290 273 258 242 226 212 198 187 176 166 162 154 148 142 137 132 127 124 120 116 112 108 105 102  99  96  93  89  85  81  79  77  75  73  71  69  67  65  63  60  57  56  55  54  53  52  51  52  53  54  55  55  55  54\n474 449 425 403 382 361 341 323 305 289 272 257 241 225 211 196 185 174 164 158 150 144 138 133 128 123 120 116 112 107 102  99  96  93  90  87  83  79  75  73  71  69  67  65  63  60  57  54  51  48  47  46  45  44  43  42  43  44  45  45  45  45  44\n474 449 425 403 382 361 341 323 305 288 271 256 240 224 210 195 183 172 162 156 148 142 136 131 126 120 116 112 108 103  98  95  92  89  86  82  78  74  70  68  66  64  62  60  57  54  51  48  45  42  41  40  39  38  37  36  36  36  36  36  36  36  35\nLift stops are: 6 15 18 25 38 49 62\nThe minimum cost is: 35\n0.010u 0.000s 0:02.29 0.4%      0+0k 0+0io 0pf+0w\n```\n\nΠαρατηρήστε ότι ο χρόνος επίλυσης παραμένει μικρός! Ποια μέθοδο θα επιλέγατε για χρήση στην\nπαραγωγή και γιατί; Δικαιολογήστε την επιλογή σας στο README και φροντίστε η επιλογή αυτή να\nείναι και η προεπιλεγμένη (default) αν ο χρήστης δεν επιλέξει κάποια από τα γνωστά modes.\n\n#### Model Context Protocol (MCP) Server — Προαιρετικό Bonus 50%\n\nΜέχρι στιγμής στο μάθημα είδαμε τρεις βασικούς τρόπους εισόδου για προγράμματα: (1)\nορίσματα στην γραμμή εντολών, (2) πρότυπη είσοδο και (3) αρχεία. Υπάρχει κάποια καλύτερη\nλύση όμως αν ο χρήστης είναι ένα σύστημα τεχνητής νοημοσύνης; Τον Νοέμβριο του 2024 η\nεταιρεία Anthropic πρότεινε το [Model Context Protocol (MCP)](https://modelcontextprotocol.io/docs/getting-started/intro),\nπου θεωρείται σήμερα *το* standard για την υλοποίηση διεπαφών για συστήματα τεχνητής\nνοημοσύνης. Παρόλο που περιέχει φοβιστικούς όρους όπως \"Server\" και \"Protocol\", στην πιο\nαπλή μορφή του είναι απλά ένα πρόγραμμα που διαβάζει από το stdin και τυπώνει στο stdout.\n\nΗ αποστολή σας λοιπόν στα πλαίσια αυτού του bonus—εφόσον την αποδεχτείτε—θα είναι η\nυλοποίηση ενός MCP server για τον elevate λύτη σας. Πιο συγκεκριμένα, θα χρειαστεί να\nυλοποιήσετε μια νέα συνάρτηση `main` σε ένα αρχείο `elevate/src/mcp.c` το οποίο θα πρέπει\nνα μεταγλωττίζεται με αντίστοιχο τρόπο όπως παραπάνω και θα προσφέρει τις ακόλουθες\nδυνατότητες:\n\n- **Initialize (Αρχικοποίηση)**. Όταν ο server σας ξεκινά, περιμένει να του στείλει κάποιος\n  χρήστης ένα μήνυμα που να ζητήσει πληροφορίες για τις δυνατότητές του και να απαντήσει\n  κατάλληλα.\n- **List Tools (Λίστα Δυνατοτήτων)**. Μετά την χειραψία το μοντέλο μπορεί να ζητήσει από τον\n  server σας να τυπώσει τις δυνατότητές του στην πρότυπη έξοδο, έτσι ώστε το σύστημα\n  τεχνητής νοημοσύνης να γνωρίζει πως να το αξιοποιήσει.\n- **Tool Call Response (Απαντήσεις σε Ερωτήσεις)**. Για κάθε ερώτηση που ταιριάζει στις\n  δυνατότητες που διαφήμισε ο server σας παραπάνω, το πρόγραμμά σας πρέπει να μπορεί να\n  προσφέρει απάντηση.\n\nΗ συνολική διάδραση είναι: ο client στέλνει `initialize` (stdin) και ο server απαντά με το\nαποτέλεσμα (stdout)· ο client στέλνει `tools/list` και ο server απαντά με τη λίστα των\nεργαλείων· ο client στέλνει `tools/call` για το `elevate` με ορίσματα, ο server τρέχει\n`elevate(numPeople, numStops, dests, mode)` και απαντά με `structuredContent`. Ας ξεκινήσουμε\nτο πρόγραμμά μας:\n\n```text\n$ gcc -Os -c -Wall -Wextra -Werror -pedantic recurse.c\n$ gcc -Os -c -Wall -Wextra -Werror -pedantic brute.c\n$ gcc -Os -c -Wall -Wextra -Werror -pedantic memoize.c\n$ gcc -Os -c -Wall -Wextra -Werror -pedantic dp.c\n$ gcc -Os -c -Wall -Wextra -Werror -pedantic mcp.c\n$ gcc -Os -o mcp recurse.o brute.o memoize.o dp.o mcp.o\n$ ./mcp\n```\n\n**Initialize.** Ο server μας περιμένει είσοδο από τον χρήστη. Ας ξεκινήσουμε την χειραψία\nστέλνοντας το αντίστοιχο μήνυμα αρχικοποίησης:\n\n```text\n{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":\n{\"protocolVersion\":\"2025-11-25\",\"capabilities\":{\"tools\":{}},\"clientInfo\":\n{\"name\":\"example-mcp-client\",\"version\":\"1.0.0\",\"title\":\"Example MCP Client\"}}}\n```\n\nΤο παραπάνω μήνυμα είναι σε μορφή [JSON](https://www.json.org/json-en.html), ενώ το όλο\nπρωτόκολλο βασίζεται σε έναν τρόπο κωδικοποίησης που λέγεται\n[JSON-RPC](https://en.wikipedia.org/wiki/JSON-RPC). Για λόγους αποδοτικότητας αποφεύγουμε\nτις καινούριες γραμμές (εδώ χρησιμοποιούνται μόνο για να φαίνεται το μήνυμα) καθώς και τα\nκενά (για να διαβάσετε ένα JSON αρχείο με καλύτερη αναγνωσιμότητα μπορείτε να τρέξετε\n`python3 -m json.tool < file.json`). Σε ένα τέτοιο μήνυμα αρχικοποίησης ο server μας πρέπει\nνα απαντήσει με το όνομά του:\n\n```text\n{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":{\"protocolVersion\":\"2025-06-18\",\"capabilities\":\n{\"experimental\":{},\"prompts\":{\"listChanged\":false},\"resources\":\n{\"subscribe\":false,\"listChanged\":false},\"tools\":{\"listChanged\":true}},\"serverInfo\":\n{\"name\":\"elevate-mcp-server\",\"version\":\"0.0.1\"}}}\n```\n\n**List Tools**. Τώρα ο χρήστης μπορεί να μάθει περισσότερα για τον server στέλνοντας το\nμήνυμα `tools/list`:\n\n```text\n{\"jsonrpc\":\"2.0\",\"id\":3,\"method\":\"tools/list\",\"params\":{}}\n```\n\nΣτο οποίο ο server μας απαντάει ως εξής:\n\n```text\n{\"jsonrpc\":\"2.0\",\"id\":3,\"result\":{\"tools\":[{\"name\":\"elevate\",\"description\":\n\"Compute the optimal elevator final stop and cost.\",\"inputSchema\":\n{\"properties\":{\"numPeople\":{\n\"description\":\"Number of people that want to use the elevator.\",\"type\":\"integer\"},\n\"numStops\":{\"description\":\"Maximum number of stops the elevator can make.\",\n\"type\":\"integer\"},\"dests\":{\"description\":\n\"Destination stop of each passenger.\",\"items\":{\"type\":\"integer\"},\"type\":\"array\"},\n\"mode\":{\"default\":\"dp\",\"description\":\n\"Solving mode to be used: recurse, brute, memoize, or dp.\",\n\"enum\":[\"recurse\",\"brute\",\"memoize\",\"dp\"],\"type\":\"string\"}},\"required\":\n[\"numPeople\",\"numStops\",\"dests\"],\"type\":\"object\"},\"outputSchema\":\n{\"description\":\"Result of the elevator optimization.\",\"properties\":{\"finalStop\":\n{\"description\":\"Chosen final elevator stop (highest floor the elevator visits).\",\n\"type\":\"integer\"},\n\"minCost\":{\"description\":\"Total minimal walking cost for all passengers.\",\n\"type\":\"integer\"},\"status\":{\"description\":\"0 on success, non-zero on error.\",\n\"type\":\"integer\"},\"message\":{\"description\":\n\"Human-readable status or error message.\",\"type\":\"string\"},\"time\":\n{\"description\":\"Elapsed time for the computation in microseconds.\",\n\"type\":\"integer\"}},\"required\":[\"finalStop\",\"minCost\",\"status\",\"message\",\"time\"],\n\"type\":\"object\"},\"_meta\":{\"_fastmcp\":{\"tags\":[]}}}]}}\n```\n\nΟ server μας τύπωσε τις δυνατότητές του (όλες τις παραμέτρους που δέχεται, περιγραφές τους\nκαθώς και τύπους) και περιμένει εντολές από το σύστημα τεχνητής νοημοσύνης.\n\n**Tool Call Response**. Ας του πούμε τι θέλουμε, κάνοντας copy-paste στο stdin:\n\n```text\n{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/call\",\"params\":\n{\"name\":\"elevate\",\"arguments\":{\"numPeople\":5,\"numStops\":2,\"dests\":\n[11,2,7,13,7],\"mode\":\"dp\"}}}\n```\n\nκαι στο stdout παρατηρούμε την απάντηση:\n\n```text\n{\"jsonrpc\":\"2.0\",\"id\":2,\"result\":{\"content\":\n[{\"type\":\"text\",\"text\":\"{\\\"finalStop\\\":11,\\\"minCost\\\":4,\\\"status\\\":0,\\\"message\\\":\n\\\"OK\\\",\\\"time\\\":15}\"}],\"structuredContent\":\n{\"finalStop\":11,\"minCost\":4,\"status\":0,\"message\":\"OK\",\"time\":15},\"isError\":false}}\n```\n\nΑυτό ήταν! Ο server μας πλέον είναι συμβατός με οποιοδήποτε σύστημα τεχνητής νοημοσύνης\nυποστηρίζει MCP, όπως το Claude Code, VS Code, Cursor, κοκ. Η εκφώνηση δείχνει μια\nενδεικτική διάδραση όπου ο server προστίθεται με `claude mcp add --transport stdio elevate\n-- ./mcp` και το μοντέλο τον καλεί για το παράδειγμα με `dests = [11,2,7,13,7]` και για\nbenchmarking όλων των modes. Αν κάποιο παιδί καταφέρει να κάνει live demo (όχι βίντεο,\nπραγματική διάδραση) της MCP σύνδεσης με κάποιο πραγματικό μοντέλο κατά την προφορική\nεξέταση, η βαθμολογία για το bonus κομμάτι διπλασιάζεται.\n\n### Επίλογος\n\nΠριν την υποβολή της εργασίας, μην ξεχάσετε το `elevate/README.md`, μέσα στο οποίο πρέπει\nνα συμπεριλάβετε τις όποιες παρατηρήσεις σας κατά την διεκπεραίωση της άσκησης! Ο κώδικας\nαπαιτείται να είναι καλά τεκμηριωμένος με σχόλια καθώς αυτό θα είναι μέρος της\nβαθμολόγησης.",
  "hint": "Ξεκίνα από μια συνάρτηση `fw(a, b)` που χειρίζεται σωστά το $b = \\infty$ και έλεγξέ την με\nτο χέρι στο πρώτο παράδειγμα (π.χ. $M_{0,j} = 40$). Για το `brute` σκέψου πώς\nαπαριθμούνται όλοι οι αύξοντες συνδυασμοί στάσεων (με αναδρομή ή με έναν «μετρητή» σαν\nοδόμετρο). Τα memoize και dp χρειάζονται πίνακα $(numStops+1) \\times (numFloors+1)$ που\nδεσμεύεται δυναμικά, με μια ειδική τιμή για «δεν υπολογίστηκε ακόμα»· για να ανακατασκευάσεις\nτις στάσεις κράτα σε δεύτερο πίνακα ποιο $k$ έδωσε το ελάχιστο και ακολούθησέ το προς τα πίσω.\nΠρόσεξε τις ισοπαλίες (προτιμώνται χαμηλότεροι όροφοι) και την περίπτωση $numStops = 0$."
 },
 {
  "id": "hw-2025-hw3-goteam",
  "kind": "homework",
  "title": "Νέα Μηχανή Go (goteam)",
  "source": {
   "title": "Εργασία 3 (2025-26), Άσκηση 1",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/hw3.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   22,
   23,
   26
  ],
  "topics": [
   "game-ai",
   "graphs",
   "multidim-arrays",
   "code-organization",
   "make",
   "strings"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α22.17",
  "path": "questions/homework/hw-2025-hw3-goteam.md",
  "url": "https://progintro.github.io/study/questions/homework/hw-2025-hw3-goteam.html",
  "statement": "Η τρίτη και τελευταία εργασία είναι **προαιρετικά ομαδική, με ομάδες μέχρι 2 άτομα**.\nΑν δουλέψετε ως ομάδα, ένας/μία από εσάς αποδέχεται την πρόσκληση και δημιουργεί την ομάδα\nμε συγκεκριμένο όνομα και ο/η συνεργάτης επιλέγει να προστεθεί σε αυτήν (**προσοχή: μην\nεπιλέξετε λάθος ομάδα**)· το repository είναι κοινό, οπότε προσοχή στα conflicts! Κάθε\nrepository **πρέπει** να έχει ένα αρχείο `AUTHORS` με μία γραμμή για κάθε άτομο, με πρώτο\nτο sdi σας, μετά το github username και τέλος το όνομά σας:\n\n```text\n$ cat AUTHORS\nsdi2500998,mourmourakis-2007,ΘΑΝΟΣ ΜΟΥΡΜΟΥΡΑΚΗΣ\nsdi2500999,lavrakis-2007,ΤΑΚΗΣ ΛΑΒΡΑΚΗΣ\n```\n\n**Υποβολές χωρίς σωστό AUTHORS αρχείο δεν θα εξεταστούν.** Αυτό ισχύει και για ατομικές\nυποβολές.\n\nΤα περισσότερα παιχνίδια ξεκινούν από μια αρχική κατάσταση και οι παίκτες εναλλάσσονται\nεπιλέγοντας κινήσεις μέχρι κάποιο κριτήριο να δείξει νίκη, ισοπαλία ή ήττα· ο χώρος\nκαταστάσεων μοιάζει με ένα $m$-αδικό δέντρο βάθους $n$ με περίπου $m^n$ καταστάσεις. Η\nτρίλιζα λύνεται εξαντλητικά σε κλάσματα δευτερολέπτου και η ντάμα λύθηκε το 2007, όμως το\n[Go](https://en.wikipedia.org/wiki/Go_(game)), σε ταμπλό 19x19 με περίπου $10^{170}$ θέσεις,\nθεωρούνταν άφταστο για την τεχνητή νοημοσύνη μέχρι που ο AlphaGo της DeepMind κέρδισε 4–1\nτον Lee Sedol το 2016. Σε αυτήν την άσκηση καλείστε να υλοποιήσετε τον πυρήνα μιας μηχανής\nGo ικανό να παίζει με αντίπαλο είτε έναν άνθρωπο, τον χρήστη του προγράμματος, είτε ένα άλλο\nπρόγραμμα, μέσω ενός ελεγκτή/διαιτητή. Μπορείτε να βρείτε στο διαδίκτυο πολλές πληροφορίες\nγια το πως δομούνται [μηχανές Go](https://en.wikipedia.org/wiki/Computer_Go).\n\n### Τεχνικές Προδιαγραφές\n\n- Repository Name: `progintro/hw3-<YourTeamName>`\n- README Filepath: `README.md`\n- Όλα τα αρχεία κώδικα (`.c` και `.h`) που θα υλοποιήσετε πρέπει να τοποθετηθούν μέσα σε\n  έναν φάκελο `src`.\n- Το project C που θα υποβληθεί πρέπει να μεταγλωττίζεται χωρίς ειδοποιήσεις για λάθη και\n  με κωδικό επιστροφής (exit code) που να είναι 0. Συγκεκριμένα, το αρχείο σας **πρέπει** να\n  μπορεί να μεταγλωττιστεί επιτυχώς με την εντολή `make` σε ένα από τα μηχανήματα του\n  εργαστηρίου (linuxXY.di.uoa.gr).\n\n  Στο repository της άσκησης σας δίνεται μια πιθανή οργάνωση κώδικα μαζί με ένα Makefile το\n  οποίο μπορείτε να συμπληρώσετε όπως θέλετε. Μπορείτε να αλλάξετε τα πάντα στο project σας,\n  αλλά θέλουμε να επιβεβαιώσετε πως η εντολή `make` συνεχίζει να δουλεύει και να παράγει\n  εκτελέσιμα για την Go μηχανή σας. **Το εκτελέσιμό σας πρέπει να λέγεται \"goteam\"**—άλλα\n  ονόματα δεν θα γίνουν δεκτά. Ακολουθήστε τις συμβάσεις που δίνονται στο αρχικό Makefile.\n- Το πρόγραμμά σας πρέπει να υποστηρίζει τις εντολές του πρωτοκόλλου\n  [Go Text Protocol (GTP)](https://www.lysator.liu.se/~gunnar/gtp/) προκειμένου να\n  επικοινωνεί με τον χρήστη ή το πρόγραμμα διαιτητή. Δείτε τις ενδεικτικές εκτελέσεις στην\n  συνέχεια για τις βασικές δυνατότητες που πρέπει να υποστηρίζει.\n- Υπάρχουν διαφορετικές εκδοχές κανόνων για το Go, στα πλαίσια της άσκησης θα ακολουθήσουμε\n  την πιο δημοφιλή εκδοχή, δηλαδή τους\n  [κινέζικους κανόνες](https://www.cs.cmu.edu/~wjh/go/rules/Chinese.html).\n- Προκειμένου να συμμετέχετε στον διαγωνισμό Go που θα γίνει στο τέλος του εξαμήνου, οι\n  εντολές του πρωτοκόλλου GTP που θα υλοποιήσετε πρέπει να είναι επαρκείς για να είναι σε\n  θέση το πρόγραμμά σας να συνεργάζεται με τους ελεγκτές/διαιτητές που θα βρείτε στην\n  διεύθυνση <https://github.com/progintro/goref>. Προκειμένου να κατεβάσετε την τελευταία\n  έκδοση του goref τοπικά (**προσοχή: θα υπάρξουν αρκετές ανανεώσεις του goref μέχρι το\n  τέλος του διαγωνισμού** προκειμένου να διαχειριστούμε την όποια ... εφευρετικότητα έχουν\n  οι λύσεις σας), μπορείτε να τρέξετε τις ακόλουθες εντολές:\n\n  ```text\n  curl -O https://raw.githubusercontent.com/progintro/goref/main/goref.py\n  chmod +x goref.py\n  ```\n\nΜία ενδεικτική εκτέλεση του προγράμματος (έστω ότι το εκτελέσιμο ονομάζεται `goteam`) είναι\nη εξής:\n\n```text\n$ ./goteam\nboardsize 5\n=\n\nkomi 0.5\n=\n\nclear_board\n=\n\nshowboard\n=\n   A B C D E\n 5 . . . . . 5\n 4 . . . . . 4\n 3 . . . . . 3\n 2 . . . . . 2\n 1 . . . . . 1\n   A B C D E\n\ngenmove black\n= C3\n\nshowboard\n=\n   A B C D E\n 5 . . . . . 5\n 4 . . . . . 4\n 3 . . X . . 3\n 2 . . . . . 2\n 1 . . . . . 1\n   A B C D E\n\nplay white C4\n=\n\ngenmove black\n= B4\n\nshowboard\n=\n   A B C D E\n 5 . . . . . 5\n 4 . X O . . 4\n 3 . . X . . 3\n 2 . . . . . 2\n 1 . . . . . 1\n   A B C D E\n\nplay white B3\n=\n\ngenmove black\n= B2\n\nshowboard\n=\n   A B C D E\n 5 . . . . . 5\n 4 . X O . . 4\n 3 . O X . . 3\n 2 . X . . . 2\n 1 . . . . . 1\n   A B C D E\n\nplay white D3\n=\n\ngenmove black\n= A3\n\nshowboard\n=\n   A B C D E\n 5 . . . . . 5\n 4 . X O . . 4\n 3 X . X O . 3\n 2 . X . . . 2\n 1 . . . . . 1\n   A B C D E\n\nplay white D5\n=\n\ngenmove black\n= E4\n\nshowboard\n=\n   A B C D E\n 5 . . . O . 5\n 4 . X O . X 4\n 3 X . X O . 3\n 2 . X . . . 2\n 1 . . . . . 1\n   A B C D E\n\nplay white C2\n=\n\ngenmove black\n= B3\n\nshowboard\n=\n   A B C D E\n 5 . . . O . 5\n 4 . X O . X 4\n 3 X X X O . 3\n 2 . X O . . 2\n 1 . . . . . 1\n   A B C D E\n\nplay white D1\n=\n\ngenmove black\n= D4\n\nshowboard\n=\n   A B C D E\n 5 . . . O . 5\n 4 . X O X X 4\n 3 X X X O . 3\n 2 . X O . . 2\n 1 . . . O . 1\n   A B C D E\n\nplay white E3\n=\n\ngenmove black\n= C5\n\nshowboard\n=\n   A B C D E\n 5 . . X O . 5\n 4 . X . X X 4\n 3 X X X O O 3\n 2 . X O . . 2\n 1 . . . O . 1\n   A B C D E\n\nplay white E2\n=\n\ngenmove black\n= B1\n\nshowboard\n=\n   A B C D E\n 5 . . X O . 5\n 4 . X . X X 4\n 3 X X X O O 3\n 2 . X O . O 2\n 1 . X . O . 1\n   A B C D E\n\nplay white C1\n=\n\ngenmove black\n= PASS\n\nshowboard\n=\n   A B C D E\n 5 . . X O . 5\n 4 . X . X X 4\n 3 X X X O O 3\n 2 . X O . O 2\n 1 . X O O . 1\n   A B C D E\n\nplay white pass\n=\n\nfinal_score\n= B+8.5\n\nquit\n=\n\n$\n```\n\n**Κύπελλο Go (BONUS βαθμολογία).** Οι μηχανές που θα υποβληθούν θα συμμετάσχουν σε κύπελλο\nGo που θα διεξαχθεί μετά το τέλος της προθεσμίας. Για τις τρεις καλύτερες υλοποιήσεις, θα\nυπάρξει επιβράβευση στη βαθμολογία τους κατά 100%, 70% και 40%, κατά σειρά. Μπορείτε να\nδοκιμάσετε τις δυνατότητες της υλοποίησής σας χρησιμοποιώντας προγράμματα διαιτητές όπως το\ngoref παραπάνω ως εξής:\n\n```text\n$ ./goref.py --black \"gnugo --mode gtp --chinese-rules\" \\\n    --white \"./goteam\" --games 10 --main-time 60 --verbose\n[blackcmd:B >>] name\n[blackcmd:B <<] = GNU Go\n[blackcmd:B <<]\n...\n[whitecmd:W >>] name\n[whitecmd:W <<] = Go Team\n[whitecmd:W <<]\n[whitecmd:W(Go Team) >>] version\n[whitecmd:W(Go Team) <<] = 1.0\n[whitecmd:W(Go Team) <<]\n...\n[whitecmd:W(Go Team) v1.0 >>] time_settings 60 0 0\n[whitecmd:W(Go Team) v1.0 <<] =\n[whitecmd:W(Go Team) v1.0 <<]\n...\n[whitecmd:W(Go Team) v1.0 >>] time_left B 60 0\n[whitecmd:W(Go Team) v1.0 <<] =\n[whitecmd:W(Go Team) v1.0 <<]\n[blackcmd:B(GNU Go) v3.8 >>] genmove B\n[blackcmd:B(GNU Go) v3.8 <<] = Q16\n[blackcmd:B(GNU Go) v3.8 <<]\n[whitecmd:W(Go Team) v1.0 >>] play B Q16\n[whitecmd:W(Go Team) v1.0 <<] =\n[whitecmd:W(Go Team) v1.0 <<]\n...\n[whitecmd:W(Go Team) v1.0 >>] time_left W 60 0\n[whitecmd:W(Go Team) v1.0 <<] =\n[whitecmd:W(Go Team) v1.0 <<]\n...\n[whitecmd:W(Go Team) v1.0 >>] genmove W\n[whitecmd:W(Go Team) v1.0 <<] = D4\n[whitecmd:W(Go Team) v1.0 <<]\n...\nGames: 10\nOverall (by command slot):\n  black_cmd: 8\n  white_cmd: 2\n  draws: 0\n...\n```\n\nΗ παραπάνω εκτέλεση ελέγχει την υλοποίησή μας με λευκά ενάντια στην μηχανή GNU Go με μαύρα\n(`apt install gnugo` σε σύστημα Ubuntu) και μας επιτρέπει να ελέγξουμε την πληρότητα αλλά\nκαι την αποδοτικότητα της υλοποίησής μας. Αν θέλετε να οπτικοποιήσετε τα αποτελέσματα της\nμηχανής σας (ή να παίξετε ένα παιχνίδι με graphical user interface) υπάρχουν αρκετές\nυλοποιήσεις ανοιχτού κώδικα που μπορείτε να χρησιμοποιήσετε, π.χ. το\n[gogui](https://github.com/Remi-Coulom/gogui).\n\n### Επίλογος\n\nΠριν την υποβολή της εργασίας, μην ξεχάσετε το `README.md`, μέσα στο οποίο πρέπει να\nσυμπεριλάβετε τις όποιες παρατηρήσεις σας κατά την διεκπεραίωση της άσκησης! Ο κώδικας\nαπαιτείται να είναι καλά τεκμηριωμένος με σχόλια καθώς αυτό θα είναι μέρος της\nβαθμολόγησης.",
  "hint": "Χώρισε το project σε επίπεδα: ανάγνωση και απάντηση εντολών GTP (γραμμή-γραμμή από το\nstdin, απάντηση `=` ή `?` και κενή γραμμή), αναπαράσταση ταμπλό, κανόνες, και τέλος επιλογή\nκίνησης. Ο πυρήνας των κανόνων είναι η εύρεση μιας ομάδας συνδεδεμένων πετρών και των\nελευθεριών της με BFS/DFS σε πλέγμα· με αυτήν υλοποιείς αιχμαλωσίες, απαγόρευση\nαυτοκτονίας, ko και την καταμέτρηση περιοχής των κινέζικων κανόνων. Ξεκίνα με μια μηχανή που\nπαίζει απλώς νόμιμες κινήσεις (και ξέρει να κάνει pass) και βελτίωσέ την μετά, π.χ. με\nπροσομοιώσεις τυχαίων παρτίδων, προσέχοντας τον χρόνο που δίνει το `time_left`."
 },
 {
  "id": "kahoot-2d-array-count",
  "kind": "kahoot",
  "title": "Πλήθος στοιχείων δισδιάστατου πίνακα",
  "source": {
   "title": "Kahoot «Δείκτες Παντού!» (διάλεξη 12) και «Πίνακες και Δείκτες» (διάλεξη 12)",
   "years": [
    2025
   ]
  },
  "chapters": [
   12
  ],
  "topics": [
   "multidim-arrays",
   "arrays"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "20",
  "stats": {
   "responses": 221,
   "accuracy": 81
  },
  "label": "Κ12.3",
  "path": "questions/kahoot/kahoot-2d-array-count.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-2d-array-count.html",
  "statement": "Ένας πίνακας `int array[4][5];` περιέχει πόσα `int` στοιχεία;\n\n- `20`\n- `12`\n- `80`\n- Εξαρτάται",
  "hint": "Ένας δισδιάστατος πίνακας είναι ένας πίνακας από γραμμές, καθεμία με τις δικές της στήλες."
 },
 {
  "id": "kahoot-2d-element-address",
  "kind": "kahoot",
  "title": "Διεύθυνση στοιχείου δισδιάστατου πίνακα",
  "source": {
   "title": "Kahoot «Πίνακες και Δείκτες» (διάλεξη 12)",
   "years": [
    2025
   ]
  },
  "chapters": [
   12
  ],
  "topics": [
   "multidim-arrays",
   "memory-model"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "320",
  "stats": {
   "responses": 141,
   "accuracy": 33
  },
  "label": "Κ12.9",
  "path": "questions/kahoot/kahoot-2d-element-address.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-2d-element-address.html",
  "statement": "Έστω ότι η διεύθυνση του `int array[10][10]` είναι 100 και `sizeof(int) == 4`. Η διεύθυνση του `array[5][5]` είναι:\n\n- `320`\n- `145`\n- `155`\n- Εξαρτάται\n\n## Συχνή παρανόηση\n\nΤο 29% επέλεξε `155`: μέτρησαν σωστά ότι προηγούνται 55 στοιχεία, αλλά ξέχασαν να τα πολλαπλασιάσουν με `sizeof(int)` για να τα κάνουν bytes.",
  "hint": "Ο πίνακας αποθηκεύεται κατά γραμμές: πόσα στοιχεία προηγούνται του `array[5][5]`, και πόσα bytes είναι το καθένα;"
 },
 {
  "id": "kahoot-2d-last-element",
  "kind": "kahoot",
  "title": "Το τελευταίο στοιχείο δισδιάστατου πίνακα",
  "source": {
   "title": "Kahoot «Πίνακες και Δείκτες» (διάλεξη 12)",
   "years": [
    2025
   ]
  },
  "chapters": [
   12
  ],
  "topics": [
   "multidim-arrays",
   "arrays"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "array[99][199]",
  "stats": {
   "responses": 141,
   "accuracy": 67
  },
  "label": "Κ12.5",
  "path": "questions/kahoot/kahoot-2d-last-element.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-2d-last-element.html",
  "statement": "Το στοιχείο της τελευταίας στήλης της τελευταίας γραμμής του πίνακα `int array[100][200];` είναι:\n\n- `array[0][0]`\n- `array[100][200]`\n- `array[99][199]`\n- `array[199][99]`",
  "hint": "Ποια διάσταση είναι οι γραμμές και ποια οι στήλες, και από πού ξεκινά η αρίθμηση;"
 },
 {
  "id": "kahoot-3d-array-dims",
  "kind": "kahoot",
  "title": "Διαστάσεις πίνακα",
  "source": {
   "title": "Kahoot «Δείκτες Παντού!» (διάλεξη 12) και «Πίνακες και Δείκτες» (διάλεξη 12)",
   "years": [
    2025
   ]
  },
  "chapters": [
   12
  ],
  "topics": [
   "multidim-arrays"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "False",
  "stats": {
   "responses": 221,
   "accuracy": 93
  },
  "label": "Κ12.1",
  "path": "questions/kahoot/kahoot-3d-array-dims.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-3d-array-dims.html",
  "statement": "Ο πίνακας `double two[2][2][2]` είναι δισδιάστατος.\n\n- True\n- False",
  "hint": "Οι διαστάσεις ενός πίνακα μετριούνται από το πλήθος των αγκυλών, όχι από τους αριθμούς μέσα τους."
 },
 {
  "id": "kahoot-address-is-integer",
  "kind": "kahoot",
  "title": "Διεύθυνση και ακέραιος",
  "source": {
   "title": "Kahoot «Δείκτες και Αναδρομή» (διάλεξη 11)",
   "years": [
    2025
   ]
  },
  "chapters": [
   11,
   2
  ],
  "topics": [
   "pointers",
   "memory-model"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "True",
  "stats": {
   "responses": 152,
   "accuracy": 50
  },
  "label": "Κ11.6",
  "path": "questions/kahoot/kahoot-address-is-integer.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-address-is-integer.html",
  "statement": "Η διεύθυνση μιας μεταβλητής είναι *πάντα* ένας ακέραιος αριθμός.\n\n- True\n- False\n\n## Συχνή παρανόηση\n\nΤο 47% απάντησε False, ίσως επειδή η διεύθυνση έχει τύπο δείκτη ή επειδή τη βλέπουμε σε δεκαεξαδικό. Όμως κάθε διεύθυνση είναι ο αύξων αριθμός ενός byte στη μνήμη, δηλαδή ακέραιος.",
  "hint": "Η μνήμη είναι μια σειρά από bytes αριθμημένα από το 0· τι είδους αριθμός είναι η θέση ενός byte;"
 },
 {
  "id": "kahoot-and-mask-ff",
  "kind": "kahoot",
  "title": "0x42 & 0xFF",
  "source": {
   "title": "Kahoot «Git και Τελεστές» (διάλεξη 4)",
   "years": [
    2025
   ]
  },
  "chapters": [
   4
  ],
  "topics": [
   "bitwise"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "0x42",
  "stats": {
   "responses": 318,
   "accuracy": 18
  },
  "label": "Κ4.8",
  "path": "questions/kahoot/kahoot-and-mask-ff.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-and-mask-ff.html",
  "statement": "Ποια η τιμή της παράστασης `0x42 & 0xFF`;\n\n- `0xFF`\n- `42`\n- `0x42`\n- `0`\n\n## Συχνή παρανόηση\n\nΤο 30% απάντησε `0`, πιθανότατα επειδή μπέρδεψε το bitwise `&` με το λογικό `&&` ή υπέθεσε ότι το AND «σβήνει» τα bits· στην πραγματικότητα το AND με `0xFF` αφήνει το byte ανέπαφο.",
  "hint": "Το `0xFF` είναι οκτώ άσοι στο δυαδικό. Τι αφήνει το bitwise AND με 1 σε κάθε bit του άλλου τελεστέου;"
 },
 {
  "id": "kahoot-argv-type",
  "kind": "kahoot",
  "title": "Ο τύπος του argv",
  "source": {
   "title": "Kahoot «Δείκτες Παντού!» (διάλεξη 12) και «Πίνακες και Δείκτες» (διάλεξη 12)",
   "years": [
    2025
   ]
  },
  "chapters": [
   12
  ],
  "topics": [
   "command-line-args",
   "pointers",
   "arrays"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "Ένας πίνακας από δείκτες σε χαρακτήρες",
  "stats": {
   "responses": 221,
   "accuracy": 44
  },
  "label": "Κ12.6",
  "path": "questions/kahoot/kahoot-argv-type.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-argv-type.html",
  "statement": "Η μεταβλητή `char *argv[]` είναι:\n\n- Ένας δισδιάστατος πίνακας από χαρακτήρες\n- Ένας δείκτης σε πίνακες από χαρακτήρες\n- Ένας πίνακας από δείκτες σε χαρακτήρες\n- Εξαρτάται\n\n## Συχνή παρανόηση\n\nΤο 34% επέλεξε «Ένας δείκτης σε πίνακες από χαρακτήρες», διαβάζοντας τη δήλωση ανάποδα. Οι αγκύλες δένουν πιο ισχυρά από το `*`, άρα το `argv` είναι πρώτα πίνακας, και τα στοιχεία του είναι `char *`.",
  "hint": "Διαβάστε τη δήλωση ξεκινώντας από το όνομα: πρώτα εφαρμόζονται οι αγκύλες και μετά το `*`."
 },
 {
  "id": "kahoot-ariane-uint16",
  "kind": "kahoot",
  "title": "Η ταχύτητα του Ariane 5",
  "source": {
   "title": "Kahoot «Μεταβλητές και Μνήμη», «Μεταβλητές και Συναρτήσεις» (διάλεξη 2)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "integer-representation",
   "types"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "$2^{16}$",
  "stats": {
   "responses": 301,
   "accuracy": 70
  },
  "label": "Κ2.6",
  "path": "questions/kahoot/kahoot-ariane-uint16.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-ariane-uint16.html",
  "statement": "Το Ariane 5 αναπαριστούσε την ταχύτητα με έναν `uint16_t`: ποια είναι η μεγαλύτερη τιμή της ταχύτητας που επιτρέπεται;\n\n- 100\n- $2^{16}$\n- 16000\n- Όλες",
  "hint": "Ένας `uint16_t` έχει 16 bits χωρίς πρόσημο· σκεφτείτε πόσες τιμές χωράνε (αυστηρά, η μεγαλύτερη είναι κατά ένα μικρότερη από το πλήθος τους, αφού ξεκινάμε από το 0)."
 },
 {
  "id": "kahoot-array-assignment",
  "kind": "kahoot",
  "title": "Αντιγραφή πίνακα με ανάθεση",
  "source": {
   "title": "Kahoot «Πίνακες» (διάλεξη 10)",
   "years": [
    2025
   ]
  },
  "chapters": [
   10
  ],
  "topics": [
   "arrays"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "False",
  "stats": {
   "responses": 249,
   "accuracy": 84
  },
  "label": "Κ10.2",
  "path": "questions/kahoot/kahoot-array-assignment.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-array-assignment.html",
  "statement": "Ο πιο αποδοτικός τρόπος για να αντιγράψω έναν πίνακα 100 στοιχείων είναι με ανάθεση:\n\n```c\nint a[100];\nint b[100];\nb = a;\n```\n\n- True\n- False",
  "hint": "Μπορεί ένα όνομα πίνακα να βρεθεί στα αριστερά μιας ανάθεσης;"
 },
 {
  "id": "kahoot-array-vs-pointer",
  "kind": "kahoot",
  "title": "Πίνακας και δείκτης",
  "source": {
   "title": "Kahoot «Δείκτες και Αναδρομή» (διάλεξη 11) και «Δείκτες Παντού!» (διάλεξη 12)",
   "years": [
    2025
   ]
  },
  "chapters": [
   11
  ],
  "topics": [
   "pointers",
   "arrays"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "False",
  "stats": {
   "responses": 232,
   "accuracy": 71
  },
  "label": "Κ11.2",
  "path": "questions/kahoot/kahoot-array-vs-pointer.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-array-vs-pointer.html",
  "statement": "Μια μεταβλητή πίνακα συμπεριφέρεται ακριβώς όπως ένας δείκτης.\n\n- True\n- False",
  "hint": "Συγκρίνετε τι επιστρέφει το `sizeof` και αν μπορείτε να αναθέσετε νέα τιμή σε καθένα από τα δύο."
 },
 {
  "id": "kahoot-arrow-operator",
  "kind": "kahoot",
  "title": "Ο τελεστής ->",
  "source": {
   "title": "Kahoot «Προχωρημένες Δομές» (διάλεξη 20), «Προχωρημένες Δομές #2»",
   "years": [
    2025
   ]
  },
  "chapters": [
   19
  ],
  "topics": [
   "structs",
   "pointers",
   "precedence"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "(*robin).hood",
  "stats": {
   "responses": 164,
   "accuracy": 48
  },
  "label": "Κ19.8",
  "path": "questions/kahoot/kahoot-arrow-operator.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-arrow-operator.html",
  "statement": "Η έκφραση `robin->hood` στην C είναι ισοδύναμη με:\n\n- `robin.(*hood)`\n- `*robin.hood`\n- `hood.robin`\n- `(*robin).hood`",
  "hint": "Το `robin` είναι δείκτης σε δομή· πρώτα πρέπει να φτάσετε στη δομή και μετά στο πεδίο, και θυμηθείτε ότι η `.` έχει μεγαλύτερη προτεραιότητα από το `*`."
 },
 {
  "id": "kahoot-ascii-next-letter",
  "kind": "kahoot",
  "title": "Ο κωδικός ASCII του 'J'",
  "source": {
   "title": "Kahoot «Μεταβλητές και Μνήμη», «Μεταβλητές και Συναρτήσεις» (διάλεξη 2)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "integer-representation",
   "types"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "0x4A",
  "stats": {
   "responses": 301,
   "accuracy": 33
  },
  "label": "Κ2.14",
  "path": "questions/kahoot/kahoot-ascii-next-letter.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-ascii-next-letter.html",
  "statement": "Εάν ο χαρακτήρας `'I'` έχει κωδικό ASCII `0x49`, ποιος είναι ο κωδικός του `'J'`;\n\n- `0x50`\n- `0x48`\n- `0x4A`\n- `0x39`\n\n## Συχνή παρανόηση\n\nΤο 44% απάντησε `0x50`, κάνοντας την πρόσθεση σαν να ήταν δεκαδικό (49 + 1 = 50)· στο δεκαεξαδικό μετά το 9 έρχεται το A.",
  "hint": "Τα γράμματα έχουν διαδοχικούς κωδικούς, άρα προσθέτετε 1. Προσοχή όμως: το `0x49` είναι δεκαεξαδικό, όχι δεκαδικό."
 },
 {
  "id": "kahoot-ask-question",
  "kind": "kahoot",
  "title": "Έχω μια ερώτηση για το μάθημα",
  "source": {
   "title": "Kahoot «Καλημέρα Κόσμε - lec00!», «Καλημέρα Κόσμε!» (διάλεξη 0)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   0
  ],
  "topics": [
   "course-intro"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "Εάν *δεν* έχει απαντηθεί στο piazza, ανοίγω νέο θέμα με περιγραφικό τίτλο",
  "stats": {
   "responses": 330,
   "accuracy": 57
  },
  "label": "Κ0.6",
  "path": "questions/kahoot/kahoot-ask-question.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-ask-question.html",
  "statement": "Έχω μια ερώτηση για το μάθημα, τι κάνω;\n\n- Την κρατάω μέσα μου και περιμένω να μου έρθει η επιφοίτηση\n- Στέλνω email στον Αυγερινό\n- Κατευθείαν ποστάρω στο piazza με τον τίτλο \"Ερώτηση\"\n- Εάν *δεν* έχει απαντηθεί στο piazza, ανοίγω νέο θέμα με περιγραφικό τίτλο\n\n## Συχνή παρανόηση\n\nΤο 23% θα πόσταρε κατευθείαν στο Piazza με τίτλο «Ερώτηση»: το Piazza είναι το σωστό κανάλι, αλλά πρώτα ψάχνουμε αν έχει ήδη απαντηθεί, και ο τίτλος πρέπει να λέει τι ρωτάμε.",
  "hint": "Σκεφτείτε πόσοι συμφοιτητές σας μπορεί να έχουν την ίδια απορία, και πώς θα βρουν εκείνοι (και εσείς) μια απάντηση που ήδη υπάρχει."
 },
 {
  "id": "kahoot-basename",
  "kind": "kahoot",
  "title": "Το basename ενός αρχείου",
  "source": {
   "title": "Kahoot «Command Line» (διάλεξη 1)",
   "years": [
    2025
   ]
  },
  "chapters": [
   1
  ],
  "topics": [
   "unix",
   "shell"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "hello.txt",
  "stats": {
   "responses": 209,
   "accuracy": 53
  },
  "label": "Κ1.7",
  "path": "questions/kahoot/kahoot-basename.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-basename.html",
  "statement": "Ποιο είναι το basename του αρχείου `/home/users/ethan/example/hello.txt`;\n\n- `/home/users/ethan/example/`\n- `example`\n- `hello.txt`\n- Δεν υπάρχει",
  "hint": "Το basename είναι το όνομα του ίδιου του αρχείου, χωρίς τους καταλόγους που οδηγούν σε αυτό."
 },
 {
  "id": "kahoot-best-search-algorithm",
  "kind": "kahoot",
  "title": "Ο καλύτερος αλγόριθμος αναζήτησης",
  "source": {
   "title": "Kahoot «Λίστες, Δέντρα and Beyond»",
   "years": [
    2025
   ]
  },
  "chapters": [
   22,
   21
  ],
  "topics": [
   "graphs",
   "trees",
   "searching"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "Εξαρτάται",
  "stats": {
   "responses": 93,
   "accuracy": 75
  },
  "label": "Κ22.2",
  "path": "questions/kahoot/kahoot-best-search-algorithm.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-best-search-algorithm.html",
  "statement": "Ποιος αλγόριθμος αναζήτησης είναι ο καλύτερος;\n\n- Breadth-First Search\n- Depth-First Search\n- Beam Search\n- Εξαρτάται",
  "hint": "Θυμηθείτε τη συζήτηση «DFS ή BFS;»: πότε κερδίζει ο καθένας, ανάλογα με το σχήμα του δέντρου και το πού βρίσκεται η λύση;"
 },
 {
  "id": "kahoot-bfs-perfect-tree",
  "kind": "kahoot",
  "title": "BFS σε τέλειο δυαδικό δέντρο",
  "source": {
   "title": "Kahoot «Λίστες, Δέντρα and Beyond»",
   "years": [
    2025
   ]
  },
  "chapters": [
   22,
   21
  ],
  "topics": [
   "trees",
   "graphs",
   "complexity",
   "searching"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "False",
  "stats": {
   "responses": 93,
   "accuracy": 37
  },
  "label": "Κ22.7",
  "path": "questions/kahoot/kahoot-bfs-perfect-tree.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-bfs-perfect-tree.html",
  "statement": "MIT (3-ετείς): έστω T ένα τέλειο δυαδικό δέντρο με n κόμβους. Μπορώ να βρω ένα στοιχείο με BFS σε O(log n);\n\n- True\n- False\n\n## Συχνή παρανόηση\n\nΤο 61% απάντησε True, μπερδεύοντας το ύψος του δέντρου (log n) με το κόστος της αναζήτησης· η BFS σε δέντρο που δεν είναι BST μπορεί να χρειαστεί να επισκεφθεί όλους τους κόμβους.",
  "hint": "Η BFS δεν ξέρει προς ποιο παιδί να πάει· σκεφτείτε πόσους κόμβους επισκέπτεται στη χειρότερη περίπτωση, αν το στοιχείο είναι στο τελευταίο επίπεδο."
 },
 {
  "id": "kahoot-big-o-sum-of-terms",
  "kind": "kahoot",
  "title": "Πολυπλοκότητα O(n² + log n)",
  "source": {
   "title": "Kahoot «Πολυπλοκότητα και άλλα» (διάλεξη 15)",
   "years": [
    2025
   ]
  },
  "chapters": [
   15
  ],
  "topics": [
   "complexity"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "True",
  "stats": {
   "responses": 124,
   "accuracy": 36
  },
  "label": "Κ15.8",
  "path": "questions/kahoot/kahoot-big-o-sum-of-terms.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-big-o-sum-of-terms.html",
  "statement": "Ένας αλγόριθμος μπορεί να έχει πολυπλοκότητα O(n² + log n).\n\n- True\n- False\n\n## Συχνή παρανόηση\n\nΤο 60% απάντησε False, θεωρώντας ότι το O(·) πρέπει να περιέχει έναν μόνο όρο· η έκφραση είναι σωστή, απλώς ισοδυναμεί με O(n²), γιατί ο κυρίαρχος όρος είναι το n².",
  "hint": "Το O(·) περιγράφει ένα άνω φράγμα με μια συνάρτηση· σκεφτείτε αν είναι λάθος να γράψουμε μια συνάρτηση που δεν έχει απλοποιηθεί, και σε τι απλοποιείται αυτή."
 },
 {
  "id": "kahoot-big-o-worst-case",
  "kind": "kahoot",
  "title": "Τι σημαίνει O(n)",
  "source": {
   "title": "Kahoot «Δυαδική Αναζήτηση, Ταξινόμηση, Πολυπλοκότητα και άλλα» και «Πολυπλοκότητα και άλλα» (διάλεξη 15)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   15
  ],
  "topics": [
   "complexity"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "στην χειρότερη (πιο αργή) περίπτωση",
  "stats": {
   "responses": 154,
   "accuracy": 62
  },
  "label": "Κ15.3",
  "path": "questions/kahoot/kahoot-big-o-worst-case.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-big-o-worst-case.html",
  "statement": "Ένας αλγόριθμος έχει χρονική πολυπλοκότητα O(n). Αυτό σημαίνει ότι χρειάζεται γραμμικό χρόνο:\n\n- στην καλύτερη (πιο γρήγορη) περίπτωση\n- στην χειρότερη (πιο αργή) περίπτωση\n- στην μέση περίπτωση\n- σε κάθε περίπτωση",
  "hint": "Το Big-O είναι άνω φράγμα· σκεφτείτε για ποια από τις περιπτώσεις ένα άνω φράγμα δίνει εγγύηση για όλες τις εισόδους."
 },
 {
  "id": "kahoot-binary-search-steps",
  "kind": "kahoot",
  "title": "Βήματα δυαδικής αναζήτησης σε 2^50 στοιχεία",
  "source": {
   "title": "Kahoot «Δυαδική Αναζήτηση και Ταξινόμηση» (διάλεξη 17) και «Δυαδική Αναζήτηση, Ταξινόμηση, Πολυπλοκότητα και άλλα»",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   17
  ],
  "topics": [
   "searching",
   "complexity"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "50",
  "stats": {
   "responses": 101,
   "accuracy": 52
  },
  "label": "Κ17.6",
  "path": "questions/kahoot/kahoot-binary-search-steps.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-binary-search-steps.html",
  "statement": "Αναζητώ έναν ακέραιο σε ταξινομημένο πίνακα με $10^{15} \\approx 2^{50}$ στοιχεία. Με δυαδική αναζήτηση θα χρειαστώ τόσα βήματα:\n\n- $10^{15}$\n- $10^{7.5}$\n- $2^{10}$\n- 50",
  "hint": "Κάθε βήμα της δυαδικής αναζήτησης υποδιπλασιάζει το διάστημα που απομένει· πόσες φορές πρέπει να διαιρέσετε το $2^{50}$ με το 2 για να φτάσετε στο 1;"
 },
 {
  "id": "kahoot-binary-search-unsorted",
  "kind": "kahoot",
  "title": "Δυαδική αναζήτηση σε μη ταξινομημένο πίνακα",
  "source": {
   "title": "Kahoot «Δυαδική Αναζήτηση και Ταξινόμηση» (διάλεξη 17)",
   "years": [
    2025
   ]
  },
  "chapters": [
   17
  ],
  "topics": [
   "searching",
   "sorting"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "False",
  "stats": {
   "responses": 71,
   "accuracy": 94
  },
  "label": "Κ17.1",
  "path": "questions/kahoot/kahoot-binary-search-unsorted.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-binary-search-unsorted.html",
  "statement": "Έχει νόημα να τρέξω δυαδική αναζήτηση σε μη ταξινομημένο πίνακα;\n\n- True\n- False",
  "hint": "Σκεφτείτε με ποιο κριτήριο η δυαδική αναζήτηση πετάει τη μισή ακολουθία σε κάθε βήμα, και τι προϋποθέτει αυτό."
 },
 {
  "id": "kahoot-bit-vs-byte",
  "kind": "kahoot",
  "title": "Bit ή byte;",
  "source": {
   "title": "Kahoot «Μεταβλητές και Μνήμη», «Μεταβλητές και Συναρτήσεις» (διάλεξη 2)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "computers"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "Byte",
  "stats": {
   "responses": 301,
   "accuracy": 93
  },
  "label": "Κ2.1",
  "path": "questions/kahoot/kahoot-bit-vs-byte.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-bit-vs-byte.html",
  "statement": "Ποια μονάδα πληροφορίας είναι μεγαλύτερη;\n\n- Bit\n- Byte",
  "hint": "Θυμηθείτε από πόσα bits αποτελείται ένα byte."
 },
 {
  "id": "kahoot-bitfield-limits",
  "kind": "kahoot",
  "title": "Περιορισμοί πεδίων bit",
  "source": {
   "title": "Kahoot «Προχωρημένες Δομές» (διάλεξη 20), «Προχωρημένες Δομές #2»",
   "years": [
    2025
   ]
  },
  "chapters": [
   20
  ],
  "topics": [
   "unions-enums",
   "structs"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "Όλα τα παραπάνω",
  "stats": {
   "responses": 164,
   "accuracy": 44
  },
  "label": "Κ20.7",
  "path": "questions/kahoot/kahoot-bitfield-limits.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-bitfield-limits.html",
  "statement": "Τι δεν μπορώ να κάνω σε bitfields (πεδία δυφίων) στην C;\n\n- Να αναφερθώ στη διεύθυνση ενός bitfield\n- Να βρω το μέγεθος με `sizeof`\n- Να αποθηκεύσω τιμές μεγαλύτερες του 2^n - 1, όπου n ο αριθμός των bits\n- Όλα τα παραπάνω\n\n## Συχνή παρανόηση\n\nΤο 26% επέλεξε μόνο το `sizeof`, χωρίς να δει ότι ένα πεδίο bit δεν έχει ούτε δική του διεύθυνση (δεν ξεκινάει απαραίτητα σε byte) ούτε χωράει τιμές πέρα από τα n bits του.",
  "hint": "Ένα πεδίο bit μπορεί να πιάνει λιγότερο από ένα byte· σκεφτείτε τι σημαίνει αυτό για τη διεύθυνση, το μέγεθος και το εύρος τιμών του."
 },
 {
  "id": "kahoot-break-only-way",
  "kind": "kahoot",
  "title": "Μόνο με break σταματά ένας βρόχος;",
  "source": {
   "title": "Kahoot «Ροή Ελέγχου #2» (διάλεξη 8)",
   "years": [
    2025
   ]
  },
  "chapters": [
   8
  ],
  "topics": [
   "control-flow",
   "loops"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "False",
  "stats": {
   "responses": 157,
   "accuracy": 94
  },
  "label": "Κ8.2",
  "path": "questions/kahoot/kahoot-break-only-way.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-break-only-way.html",
  "statement": "Η εντολή `break` είναι ο μόνος τρόπος για να σταματήσουμε έναν βρόχο;\n\n- True\n- False",
  "hint": "Σκεφτείτε πώς τελειώνει ένας συνηθισμένος βρόχος `for (i = 0; i < 10; i++)` και τι άλλο είδαμε, π.χ. μεταβλητές-σημαίες ή `return`."
 },
 {
  "id": "kahoot-bst-sorted-traversal",
  "kind": "kahoot",
  "title": "Ταξινομημένη εκτύπωση BST",
  "source": {
   "title": "Kahoot «Λίστες, Δέντρα and Beyond»",
   "years": [
    2025
   ]
  },
  "chapters": [
   22,
   21
  ],
  "topics": [
   "trees",
   "recursion",
   "sorting"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "inorder",
  "stats": {
   "responses": 93,
   "accuracy": 66
  },
  "label": "Κ22.3",
  "path": "questions/kahoot/kahoot-bst-sorted-traversal.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-bst-sorted-traversal.html",
  "statement": "Έστω ότι έχω ένα δυαδικό δέντρο αναζήτησης. Για να τυπώσω τα στοιχεία του ταξινομημένα, χρησιμοποιώ διάσχιση:\n\n- preorder\n- inorder\n- postorder\n- Δεν γίνεται",
  "hint": "Σε ένα BST τα μικρότερα στοιχεία είναι αριστερά και τα μεγαλύτερα δεξιά· πότε πρέπει να τυπώνεται η ρίζα σε σχέση με τα δύο υποδέντρα;"
 },
 {
  "id": "kahoot-bst-worst-case",
  "kind": "kahoot",
  "title": "Χειρότερη περίπτωση αναζήτησης σε BST",
  "source": {
   "title": "Kahoot «Λίστες, Δέντρα and Beyond»",
   "years": [
    2025
   ]
  },
  "chapters": [
   22,
   21
  ],
  "topics": [
   "trees",
   "complexity",
   "searching"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "Όταν το δέντρο είναι εκφυλισμένο",
  "stats": {
   "responses": 93,
   "accuracy": 29
  },
  "label": "Κ22.9",
  "path": "questions/kahoot/kahoot-bst-worst-case.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-bst-worst-case.html",
  "statement": "Έχω ένα δυαδικό δέντρο αναζήτησης (BST) με n κόμβους. Μπορεί να χρειαστώ O(n) χρόνο για να βρω ένα στοιχείο:\n\n- Όταν το δέντρο είναι τέλειο και έχει όλα τα φύλλα\n- Όταν το δέντρο είναι εκφυλισμένο\n- Όταν το δέντρο είναι ισορροπημένο και δεν ξέρω προς τα που να ψάξω\n- Δεν γίνεται, σε BST πάντα χρειάζομαι O(logn)\n\n## Συχνή παρανόηση\n\nΤο 30% επέλεξε το ισορροπημένο δέντρο, ενώ σε ισορροπημένο BST η σύγκριση με κάθε κόμβο δείχνει πάντα προς τα πού να ψάξουμε, άρα αρκούν O(log n) βήματα.",
  "hint": "Το κόστος της αναζήτησης σε BST είναι ανάλογο του ύψους του· πότε το ύψος γίνεται ίσο με n;"
 },
 {
  "id": "kahoot-bubblesort-complexity",
  "kind": "kahoot",
  "title": "Πολυπλοκότητα της bubblesort",
  "source": {
   "title": "Kahoot «Δυαδική Αναζήτηση και Ταξινόμηση» (διάλεξη 17)",
   "years": [
    2025
   ]
  },
  "chapters": [
   17
  ],
  "topics": [
   "sorting",
   "complexity"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "O(n²)",
  "stats": {
   "responses": 71,
   "accuracy": 75
  },
  "label": "Κ17.3",
  "path": "questions/kahoot/kahoot-bubblesort-complexity.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-bubblesort-complexity.html",
  "statement": "Ποια η χρονική πολυπλοκότητα της bubblesort;\n\n- O(n)\n- O(n²)\n- O(log n)\n- O(n log n)",
  "hint": "Μετρήστε πόσα περάσματα κάνει ο αλγόριθμος στη χειρότερη περίπτωση και πόσες συγκρίσεις γίνονται σε κάθε πέρασμα."
 },
 {
  "id": "kahoot-byte-values",
  "kind": "kahoot",
  "title": "Τιμές ενός byte",
  "source": {
   "title": "Kahoot «Μεταβλητές και Μνήμη», «Μεταβλητές και Συναρτήσεις» (διάλεξη 2)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "computers",
   "integer-representation"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "$2^8$",
  "stats": {
   "responses": 301,
   "accuracy": 78
  },
  "label": "Κ2.5",
  "path": "questions/kahoot/kahoot-byte-values.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-byte-values.html",
  "statement": "Πόσες διαφορετικές τιμές μπορεί να πάρει ένα 8-bit byte;\n\n- $2^8$\n- $2^{16}$\n- 8\n- 16",
  "hint": "Κάθε bit έχει δύο δυνατές τιμές, ανεξάρτητα από τα υπόλοιπα."
 },
 {
  "id": "kahoot-c-main-feature",
  "kind": "kahoot",
  "title": "Το χαρακτηριστικό της C",
  "source": {
   "title": "Kahoot «Καλημέρα Κόσμε - lec00!» (διάλεξη 0)",
   "years": [
    2025
   ]
  },
  "chapters": [
   0
  ],
  "topics": [
   "course-intro"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "Όλα τα παραπάνω",
  "stats": {
   "responses": 113,
   "accuracy": 61
  },
  "label": "Κ0.5",
  "path": "questions/kahoot/kahoot-c-main-feature.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-c-main-feature.html",
  "statement": "Ποιο είναι το κύριο χαρακτηριστικό της γλώσσας C;\n\n- Δημοφιλής\n- Γρήγορη/Αποδοτική\n- Χρησιμοποιείται παντού\n- Όλα τα παραπάνω\n\n## Συχνή παρανόηση\n\nΤο 27% διάλεξε «Γρήγορη/Αποδοτική»: η ταχύτητα είναι πράγματι ένα από τα πλεονεκτήματα της C, αλλά όχι το μόνο που τονίστηκε.",
  "hint": "Σκεφτείτε τους λόγους που δόθηκαν στη διάλεξη για την επιλογή της C: ισχύει μόνο ένας;"
 },
 {
  "id": "kahoot-c-program-functions",
  "kind": "kahoot",
  "title": "Από τι αποτελείται ένα πρόγραμμα C",
  "source": {
   "title": "Kahoot «Τύπωμα και Συναρτήσεις» (διάλεξη 3)",
   "years": [
    2025
   ]
  },
  "chapters": [
   3
  ],
  "topics": [
   "functions"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "Μια σειρά από συναρτήσεις",
  "stats": {
   "responses": 190,
   "accuracy": 55
  },
  "label": "Κ3.3",
  "path": "questions/kahoot/kahoot-c-program-functions.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-c-program-functions.html",
  "statement": "Ένα πρόγραμμα C είναι συνήθως:\n\n- Μια σειρά από συναρτήσεις\n- Η συνάρτηση main\n- Μια σειρά από τελεστές\n- Μια σειρά από εντολές\n\n## Συχνή παρανόηση\n\nΤο 30% επέλεξε «μια σειρά από εντολές»· οι εντολές όμως υπάρχουν μόνο μέσα στο σώμα συναρτήσεων, και το πρόγραμμα οργανώνεται σε συναρτήσεις, με πρώτη τη `main`.",
  "hint": "Οι εντολές δεν μπορούν να βρίσκονται «ελεύθερες» σε ένα αρχείο C· σκεφτείτε μέσα σε τι γράφονται πάντα."
 },
 {
  "id": "kahoot-cast-truncation",
  "kind": "kahoot",
  "title": "Μετατροπή double σε int",
  "source": {
   "title": "Kahoot «Τελεστές, Εντολές και Ροή Ελέγχου» (διάλεξη 6)",
   "years": [
    2025
   ]
  },
  "chapters": [
   5
  ],
  "topics": [
   "operators",
   "types"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "42",
  "stats": {
   "responses": 245,
   "accuracy": 86
  },
  "label": "Κ5.1",
  "path": "questions/kahoot/kahoot-cast-truncation.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-cast-truncation.html",
  "statement": "Τι επιστρέφει η παράσταση `(int)42.842`;\n\n- 42\n- 43\n- 42.8\n- 42.842",
  "hint": "Ο τελεστής μετατροπής σε `int` κρατά μόνο το ακέραιο μέρος· στρογγυλοποιεί ή αποκόπτει;"
 },
 {
  "id": "kahoot-cat-prints-file",
  "kind": "kahoot",
  "title": "Εκτύπωση περιεχομένων αρχείου",
  "source": {
   "title": "Kahoot «Command Line» (διάλεξη 1)",
   "years": [
    2025
   ]
  },
  "chapters": [
   1
  ],
  "topics": [
   "shell",
   "unix"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "cat",
  "stats": {
   "responses": 209,
   "accuracy": 29
  },
  "label": "Κ1.9",
  "path": "questions/kahoot/kahoot-cat-prints-file.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-cat-prints-file.html",
  "statement": "Ποια από τις παρακάτω εντολές τυπώνει τα περιεχόμενα ενός αρχείου;\n\n- `printf`\n- `cat`\n- `dog`\n- `echo`\n\n## Συχνή παρανόηση\n\nΤο 47% διάλεξε `printf`, μπερδεύοντας τη συνάρτηση της C (και την ομώνυμη εντολή του shell), που τυπώνει το κείμενο που της δίνουμε, με μια εντολή που διαβάζει αρχεία.",
  "hint": "Ποια εντολή παίρνει ως όρισμα ένα όνομα αρχείου (και όχι ένα κείμενο) και στέλνει ό,τι περιέχει στην έξοδο;"
 },
 {
  "id": "kahoot-char-array-address",
  "kind": "kahoot",
  "title": "Διεύθυνση στοιχείου πίνακα char",
  "source": {
   "title": "Kahoot «Πίνακες» (διάλεξη 10)",
   "years": [
    2025
   ]
  },
  "chapters": [
   10
  ],
  "topics": [
   "arrays",
   "memory-model"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "1042",
  "stats": {
   "responses": 249,
   "accuracy": 19
  },
  "label": "Κ10.10",
  "path": "questions/kahoot/kahoot-char-array-address.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-char-array-address.html",
  "statement": "Αν ο πίνακας `char array[100];` ξεκινάει στη διεύθυνση 1000, σε ποια διεύθυνση βρίσκεται το στοιχείο `array[42]`;\n\n- `1000`\n- `1042`\n- `1041`\n- `1043`\n\n## Συχνή παρανόηση\n\nΤο 52% επέλεξε `1041`, μετρώντας τις θέσεις σαν να ξεκινούσαν από το 1. Αφού το `array[0]` είναι στο 1000 και κάθε `char` πιάνει 1 byte, το `array[i]` είναι στο 1000 + i.",
  "hint": "Ποια είναι η διεύθυνση του `array[0]`, και πόσα bytes πιάνει κάθε `char`;"
 },
 {
  "id": "kahoot-char-array-storage",
  "kind": "kahoot",
  "title": "Πού αποθηκεύεται το char str[]",
  "source": {
   "title": "Kahoot «Δυαδική Αναζήτηση, Ταξινόμηση, Πολυπλοκότητα και άλλα» και «Εμβέλεια, Μνήμη και Συμβολοσειρές» (διάλεξη 14)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   14,
   13
  ],
  "topics": [
   "memory-model",
   "strings",
   "scope"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "Στην στοίβα ή στατική μνήμη ανάλογα με το σημείο δήλωσης",
  "stats": {
   "responses": 127,
   "accuracy": 49
  },
  "label": "Κ14.4",
  "path": "questions/kahoot/kahoot-char-array-storage.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-char-array-storage.html",
  "statement": "Παλιό θέμα: Η εντολή `char str[] = \"hello\";` αποθηκεύει τον πίνακα `str`:\n\n- Στην στοίβα\n- Στον σωρό\n- Στην στατική μνήμη\n- Στην στοίβα ή στατική μνήμη ανάλογα με το σημείο δήλωσης\n\n## Συχνή παρανόηση\n\nΤο 31% απάντησε «Στην στοίβα», υποθέτοντας σιωπηρά ότι η δήλωση είναι μέσα σε συνάρτηση· αν είναι παγκόσμια, ο πίνακας βρίσκεται στη στατική μνήμη.",
  "hint": "Η εντολή δεν λέει πού βρίσκεται: μέσα σε συνάρτηση ή έξω από κάθε συνάρτηση; Θυμηθείτε πού ζει μια τοπική και πού μια παγκόσμια μεταβλητή."
 },
 {
  "id": "kahoot-charcount-eof",
  "kind": "kahoot",
  "title": "Μετρητής χαρακτήρων μέχρι την αλλαγή γραμμής",
  "source": {
   "title": "Kahoot «Δεδομένα Εισόδου» (διάλεξη 9)",
   "years": [
    2025
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output",
   "loops"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "Δεν θα τερματίσει ποτέ εάν ο χρήστης δώσει EOF",
  "stats": {
   "responses": 244,
   "accuracy": 31
  },
  "label": "Κ9.7",
  "path": "questions/kahoot/kahoot-charcount-eof.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-charcount-eof.html",
  "statement": "Τι ισχύει για το πρόγραμμα:\n\n```c\nwhile ((c = getchar()) != '\\n')\n    charcount++;\nprintf(\"%d\", charcount);\n```\n\n- Θα τυπώνει 0 1 2 3 μέχρι να δώσει ο χρήστης αλλαγή γραμμής\n- Δεν είναι δεκτή C\n- Δεν θα τερματίσει ποτέ εάν ο χρήστης δώσει EOF\n- tl;dr\n\n## Συχνή παρανόηση\n\nΤο 36% επέλεξε ότι θα τυπώνει 0 1 2 3 …, θεωρώντας ότι η `printf` είναι μέσα στον βρόχο· χωρίς άγκιστρα το σώμα της `while` είναι μόνο η `charcount++;`.",
  "hint": "Δείτε ποια εντολή ανήκει στο σώμα του βρόχου, και τι επιστρέφει η `getchar` κάθε φορά που την καλούμε αφού η είσοδος έχει τελειώσει."
 },
 {
  "id": "kahoot-comment-syntax",
  "kind": "kahoot",
  "title": "Πώς γράφουμε σχόλια",
  "source": {
   "title": "Kahoot «Επίλυση Προβλημάτων» (διάλεξη 7)",
   "years": [
    2025
   ]
  },
  "chapters": [
   7,
   0
  ],
  "topics": [
   "good-practice"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "/* this way */, // wrong again!",
  "stats": {
   "responses": 192,
   "accuracy": 46
  },
  "label": "Κ7.5",
  "path": "questions/kahoot/kahoot-comment-syntax.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-comment-syntax.html",
  "statement": "Πώς βάζω σχόλια στο πρόγραμμά μου; (Επιλέξτε όλες τις σωστές απαντήσεις.)\n\n- `/* this way */`\n- `*/ nope this is the way /*`\n- `// wrong again!`\n- `\\\\ the only correct answer is 42`",
  "hint": "Η C έχει δύο είδη σχολίων: ένα για σχόλια πολλών γραμμών και ένα για σχόλια μέχρι το τέλος της γραμμής. Προσέξτε τη σειρά και τη φορά των χαρακτήρων."
 },
 {
  "id": "kahoot-comments-good-practice",
  "kind": "kahoot",
  "title": "Αξίζει να σχολιάζω τον κώδικα;",
  "source": {
   "title": "Kahoot «Τύπωμα και Συναρτήσεις» (διάλεξη 3)",
   "years": [
    2025
   ]
  },
  "chapters": [
   7
  ],
  "topics": [
   "good-practice"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "True",
  "stats": {
   "responses": 190,
   "accuracy": 91
  },
  "label": "Κ7.1",
  "path": "questions/kahoot/kahoot-comments-good-practice.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-comments-good-practice.html",
  "statement": "Είναι καλή πρακτική να βάζω σχόλια στον κώδικά μου;\n\n- True\n- False",
  "hint": "Σκεφτείτε ποιος θα διαβάσει τον κώδικά σας σε έναν μήνα (ίσως εσείς)."
 },
 {
  "id": "kahoot-count-digits",
  "kind": "kahoot",
  "title": "Πολυπλοκότητα μέτρησης ψηφίων",
  "source": {
   "title": "Kahoot «Δυαδική Αναζήτηση, Ταξινόμηση, Πολυπλοκότητα και άλλα» και «Πολυπλοκότητα και άλλα» (διάλεξη 15)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   15
  ],
  "topics": [
   "complexity",
   "math-algorithms"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "O(log n)",
  "stats": {
   "responses": 154,
   "accuracy": 38
  },
  "label": "Κ15.6",
  "path": "questions/kahoot/kahoot-count-digits.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-count-digits.html",
  "statement": "Μετράω τα ψηφία οποιουδήποτε αριθμού n μου δοθεί. Η χρονική πολυπλοκότητα του αλγορίθμου μου είναι:\n\n- O(n)\n- O(n²)\n- O(f(x))\n- O(log n)\n\n## Συχνή παρανόηση\n\nΤο 45% επέλεξε O(n), μπερδεύοντας την τιμή του n με το μέγεθος της εισόδου: ο αλγόριθμος κάνει μία επανάληψη ανά ψηφίο, όχι ανά μονάδα της τιμής.",
  "hint": "Πόσες φορές μπορείτε να διαιρέσετε το n με το 10 πριν φτάσει στο 0; Συγκρίνετε το πλήθος των ψηφίων του 1000 και του 1000000."
 },
 {
  "id": "kahoot-count-set-bits",
  "kind": "kahoot",
  "title": "Πολυπλοκότητα μέτρησης bit",
  "source": {
   "title": "Kahoot «Πολυπλοκότητα και άλλα» (διάλεξη 15)",
   "years": [
    2025
   ]
  },
  "chapters": [
   15,
   5
  ],
  "topics": [
   "complexity",
   "bitwise"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "O(log n)",
  "stats": {
   "responses": 124,
   "accuracy": 43
  },
  "label": "Κ15.5",
  "path": "questions/kahoot/kahoot-count-set-bits.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-count-set-bits.html",
  "statement": "Μια συνάρτηση παίρνει έναν αριθμό n και επιστρέφει πόσα bit είναι 1. Πόσο γρήγορη μπορώ να κάνω αυτήν τη συνάρτηση;\n\n- O(n³)\n- O(n²)\n- O(n)\n- O(f(x))\n- O(log n)\n\n## Συχνή παρανόηση\n\nΤο 32% επέλεξε O(n), μπερδεύοντας την τιμή του n με το πλήθος των bit του, που είναι περίπου $\\log_2 n$.",
  "hint": "Πόσα bit χρειάζονται για να γράψετε τον αριθμό n στο δυαδικό;"
 },
 {
  "id": "kahoot-course-form",
  "kind": "kahoot",
  "title": "Η φόρμα του μαθήματος",
  "source": {
   "title": "Kahoot «Καλημέρα Κόσμε - lec00!», «Καλημέρα Κόσμε!» (διάλεξη 0)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   0
  ],
  "topics": [
   "course-intro"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "False",
  "stats": {
   "responses": 330,
   "accuracy": 85
  },
  "label": "Κ0.3",
  "path": "questions/kahoot/kahoot-course-form.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-course-form.html",
  "statement": "Δεν συμπλήρωσα τη φόρμα του μαθήματος, υπάρχει περίπτωση να βαθμολογηθούν οι ασκήσεις μου;\n\n- True\n- False",
  "hint": "Θυμηθείτε τη λίστα με τα βήματα εγγραφής στα εργαλεία του μαθήματος, και σκεφτείτε πώς αντιστοιχίζονται οι υποβολές σας με εσάς."
 },
 {
  "id": "kahoot-course-tools",
  "kind": "kahoot",
  "title": "Τα εργαλεία του μαθήματος",
  "source": {
   "title": "Kahoot «Καλημέρα Κόσμε - lec00!» (διάλεξη 0)",
   "years": [
    2025
   ]
  },
  "chapters": [
   0
  ],
  "topics": [
   "course-intro"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "Όλα τα παραπάνω",
  "stats": {
   "responses": 113,
   "accuracy": 82
  },
  "label": "Κ0.4",
  "path": "questions/kahoot/kahoot-course-tools.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-course-tools.html",
  "statement": "Ποιο από τα παρακάτω είναι εργαλείο του μαθήματος;\n\n- Piazza\n- GitHub\n- E-Class\n- Όλα τα παραπάνω",
  "hint": "Θυμηθείτε πού γίνονται οι συζητήσεις, πού υποβάλλονται οι ασκήσεις και πού βρίσκονται οι ανακοινώσεις."
 },
 {
  "id": "kahoot-custom-types",
  "kind": "kahoot",
  "title": "Δικοί μας τύποι",
  "source": {
   "title": "Kahoot «Δομές + Αρχεία», «Ταξινόμηση και Δομές»",
   "years": [
    2025
   ]
  },
  "chapters": [
   19
  ],
  "topics": [
   "structs",
   "types"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "True",
  "stats": {
   "responses": 151,
   "accuracy": 81
  },
  "label": "Κ19.1",
  "path": "questions/kahoot/kahoot-custom-types.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-custom-types.html",
  "statement": "Μπορώ να ορίσω δικούς μου τύπους στην C.\n\n- True\n- False",
  "hint": "Σκεφτείτε τι κάνουν οι λέξεις-κλειδιά `struct` και `typedef`."
 },
 {
  "id": "kahoot-define-macro",
  "kind": "kahoot",
  "title": "Ορισμός μακροεντολής",
  "source": {
   "title": "Kahoot «Πολυπλοκότητα και άλλα» (διάλεξη 15)",
   "years": [
    2025
   ]
  },
  "chapters": [
   15
  ],
  "topics": [
   "preprocessor"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "#define",
  "stats": {
   "responses": 124,
   "accuracy": 74
  },
  "label": "Κ15.2",
  "path": "questions/kahoot/kahoot-define-macro.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-define-macro.html",
  "statement": "Για να ορίσω μια μακροεντολή (macro) χρησιμοποιώ την εντολή:\n\n- `#ifdef`\n- `#include`\n- `#define`\n- `#ifndef`",
  "hint": "Από τις τέσσερις οδηγίες, δύο αφορούν μεταγλώττιση υπό συνθήκη και μία την εισαγωγή αρχείου."
 },
 {
  "id": "kahoot-deref-address-of",
  "kind": "kahoot",
  "title": "Η έκφραση *&x",
  "source": {
   "title": "Kahoot «Δείκτες και Αναδρομή» (διάλεξη 11) και «Δείκτες Παντού!» (διάλεξη 12)",
   "years": [
    2025
   ]
  },
  "chapters": [
   11
  ],
  "topics": [
   "pointers",
   "operators"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "Ισοδύναμη με την εντολή y = x;",
  "stats": {
   "responses": 232,
   "accuracy": 35
  },
  "label": "Κ11.10",
  "path": "questions/kahoot/kahoot-deref-address-of.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-deref-address-of.html",
  "statement": "Παλιό θέμα: η εντολή `y = *&x;` στη C είναι:\n\n- Ισοδύναμη με την εντολή `y = x;`\n- Ισοδύναμη με την εντολή `y = &*x;`\n- Ισοδύναμη με την εντολή `y = *x;`\n- Συντακτικά λανθασμένη",
  "hint": "Οι τελεστές `*` και `&` είναι συμπληρωματικοί: τι κάνει ο καθένας στο αποτέλεσμα του άλλου;"
 },
 {
  "id": "kahoot-deref-increment",
  "kind": "kahoot",
  "title": "Αύξηση μέσω δείκτη",
  "source": {
   "title": "Kahoot «Δείκτες και Αναδρομή» (διάλεξη 11) και «Δείκτες Παντού!» (διάλεξη 12)",
   "years": [
    2025
   ]
  },
  "chapters": [
   11
  ],
  "topics": [
   "pointers",
   "precedence"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "42",
  "stats": {
   "responses": 232,
   "accuracy": 34
  },
  "label": "Κ11.11",
  "path": "questions/kahoot/kahoot-deref-increment.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-deref-increment.html",
  "statement": "Τι θα τυπώσει ο παρακάτω κώδικας;\n\n```c\nint x = 41;\nint *ptr = &x;\n(*ptr)++;\nprintf(\"%d\", *ptr);\n```\n\n- `41`\n- `42`\n- `43`\n- Που να ξέρω",
  "hint": "Οι παρενθέσεις ορίζουν σε τι εφαρμόζεται το `++`: στον ίδιο τον δείκτη ή σε αυτό που δείχνει;"
 },
 {
  "id": "kahoot-double-free",
  "kind": "kahoot",
  "title": "Διπλό free",
  "source": {
   "title": "Kahoot «Μνήμη» (διάλεξη 13)",
   "years": [
    2025
   ]
  },
  "chapters": [
   13
  ],
  "topics": [
   "dynamic-memory",
   "undefined-behavior"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "False",
  "stats": {
   "responses": 135,
   "accuracy": 92
  },
  "label": "Κ13.1",
  "path": "questions/kahoot/kahoot-double-free.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-double-free.html",
  "statement": "Για να είμαι βέβαιος ότι απελευθέρωσα τη μνήμη στον σωρό, τρέχω `free` δύο φορές χωρίς έλεγχο.\n\n- True\n- False",
  "hint": "Τι συμβαίνει αν δώσετε στην `free` έναν δείκτη σε μνήμη που έχει ήδη αποδεσμευτεί;"
 },
 {
  "id": "kahoot-echo-second-arg",
  "kind": "kahoot",
  "title": "Το 2ο όρισμα του echo",
  "source": {
   "title": "Kahoot «Command Line» (διάλεξη 1)",
   "years": [
    2025
   ]
  },
  "chapters": [
   1,
   4
  ],
  "topics": [
   "shell",
   "command-line-args"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "good",
  "stats": {
   "responses": 209,
   "accuracy": 73
  },
  "label": "Κ1.2",
  "path": "questions/kahoot/kahoot-echo-second-arg.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-echo-second-arg.html",
  "statement": "Στην εντολή `/bin/echo hello good world` ποιο είναι το 2ο όρισμα του προγράμματος;\n\n- `echo`\n- `hello`\n- `good`\n- `world`",
  "hint": "Το shell χωρίζει τη γραμμή σε λέξεις με βάση τα κενά· η πρώτη λέξη είναι το πρόγραμμα που εκτελείται, και τα ορίσματα μετράνε από τη λέξη μετά από αυτό."
 },
 {
  "id": "kahoot-enum-values",
  "kind": "kahoot",
  "title": "Τιμές απαρίθμησης",
  "source": {
   "title": "Kahoot «Προχωρημένες Δομές» (διάλεξη 20), «Προχωρημένες Δομές #2»",
   "years": [
    2025
   ]
  },
  "chapters": [
   20
  ],
  "topics": [
   "unions-enums"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "2",
  "stats": {
   "responses": 164,
   "accuracy": 48
  },
  "label": "Κ20.6",
  "path": "questions/kahoot/kahoot-enum-values.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-enum-values.html",
  "statement": "Έστω `enum TrafficLight {Red = 0, Yellow, Green};`. Ποια η τιμή του `Green`;\n\n- 0\n- 1\n- 2\n- 'G'",
  "hint": "Οι σταθερές μιας απαρίθμησης είναι ακέραιοι· αν δεν δοθεί τιμή, κάθε σταθερά παίρνει την τιμή της προηγούμενης συν 1."
 },
 {
  "id": "kahoot-eof-key",
  "kind": "kahoot",
  "title": "Πώς στέλνω EOF",
  "source": {
   "title": "Kahoot «Δεδομένα Εισόδου» (διάλεξη 9)",
   "years": [
    2025
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output",
   "shell"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "Ctrl+D",
  "stats": {
   "responses": 244,
   "accuracy": 90
  },
  "label": "Κ9.2",
  "path": "questions/kahoot/kahoot-eof-key.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-eof-key.html",
  "statement": "Ποιος είναι ο συνδυασμός πλήκτρων για να στείλω EOF στο πρόγραμμά μου;\n\n- Ctrl+Alt+Delete\n- Ctrl+C\n- Ctrl+D\n- Ctrl+V",
  "hint": "Ο ένας από τους συνδυασμούς διακόπτει βίαια το πρόγραμμα· εμείς θέλουμε να του πούμε ευγενικά ότι «δεν έχει άλλα δεδομένα»."
 },
 {
  "id": "kahoot-eof-value",
  "kind": "kahoot",
  "title": "Η τιμή του EOF",
  "source": {
   "title": "Kahoot «Δεδομένα Εισόδου» (διάλεξη 9)",
   "years": [
    2025
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "-1",
  "stats": {
   "responses": 244,
   "accuracy": 79
  },
  "label": "Κ9.4",
  "path": "questions/kahoot/kahoot-eof-value.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-eof-value.html",
  "statement": "Η τιμή `EOF` είναι συνήθως ίση με τον ακέραιο:\n\n- 1\n- 0\n- -1\n- 42",
  "hint": "Η τιμή του `EOF` πρέπει να διαφέρει από κάθε έγκυρο χαρακτήρα, που διαβάζεται ως τιμή από 0 έως 255."
 },
 {
  "id": "kahoot-everything-is-a-file",
  "kind": "kahoot",
  "title": "Στο Linux όλα είναι…",
  "source": {
   "title": "Kahoot «Command Line» (διάλεξη 1)",
   "years": [
    2025
   ]
  },
  "chapters": [
   1
  ],
  "topics": [
   "unix"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "Αρχείο",
  "stats": {
   "responses": 209,
   "accuracy": 71
  },
  "label": "Κ1.4",
  "path": "questions/kahoot/kahoot-everything-is-a-file.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-everything-is-a-file.html",
  "statement": "Στο Linux (σχεδόν) όλα είναι ένα:\n\n- Ψέμα\n- Αρχείο\n- IP Address\n- Κλικ",
  "hint": "Θυμηθείτε τη φιλοσοφία του Unix για το σύστημα αρχείων: ακόμα και οι συσκευές εμφανίζονται κάτω από το `/dev`."
 },
 {
  "id": "kahoot-excess-initializers",
  "kind": "kahoot",
  "title": "Αρχικοποίηση με περισσότερες τιμές",
  "source": {
   "title": "Kahoot «Πίνακες» (διάλεξη 10)",
   "years": [
    2025
   ]
  },
  "chapters": [
   10
  ],
  "topics": [
   "arrays"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "False",
  "stats": {
   "responses": 249,
   "accuracy": 71
  },
  "label": "Κ10.5",
  "path": "questions/kahoot/kahoot-excess-initializers.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-excess-initializers.html",
  "statement": "Μπορούμε να αρχικοποιήσουμε έναν πίνακα με 10 ακεραίους ως εξής:\n\n```c\nint numbers[10] = {0,1,2,3,4,5,6,7,8,9,10};\n```\n\n- True\n- False",
  "hint": "Μετρήστε πόσες τιμές έχει η λίστα αρχικοποίησης και συγκρίνετε με το μέγεθος του πίνακα."
 },
 {
  "id": "kahoot-expression-tree-eval",
  "kind": "kahoot",
  "title": "Αποτίμηση δέντρου εκφράσεων",
  "source": {
   "title": "Kahoot «Λίστες, Δέντρα and Beyond»",
   "years": [
    2025
   ]
  },
  "chapters": [
   22
  ],
  "topics": [
   "trees",
   "recursion"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "postorder",
  "stats": {
   "responses": 93,
   "accuracy": 35
  },
  "label": "Κ22.8",
  "path": "questions/kahoot/kahoot-expression-tree-eval.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-expression-tree-eval.html",
  "statement": "Θέλω να γράψω έναν αποτιμητή εκφράσεων που αναπαρίστανται με δέντρα. Προτιμώ διάσχιση:\n\n- preorder\n- inorder\n- postorder\n- Δεν χρειάζομαι διάσχιση, το κάνω σε O(1)\n\n## Συχνή παρανόηση\n\nΤο 28% επέλεξε preorder, όμως για να εφαρμόσουμε τον τελεστή της ρίζας χρειαζόμαστε πρώτα τις τιμές και των δύο υποδέντρων.",
  "hint": "Σε έναν κόμβο `+` με παιδιά τις υποεκφράσεις, τι πρέπει να έχετε υπολογίσει πριν κάνετε την πρόσθεση;"
 },
 {
  "id": "kahoot-filepath",
  "kind": "kahoot",
  "title": "Το μονοπάτι ενός αρχείου",
  "source": {
   "title": "Kahoot «Command Line» (διάλεξη 1)",
   "years": [
    2025
   ]
  },
  "chapters": [
   1
  ],
  "topics": [
   "unix",
   "shell"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "/home/users/ethan/example/hello.txt",
  "stats": {
   "responses": 209,
   "accuracy": 20
  },
  "label": "Κ1.10",
  "path": "questions/kahoot/kahoot-filepath.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-filepath.html",
  "statement": "Ποιο είναι το filepath του αρχείου `/home/users/ethan/example/hello.txt`;\n\n- `/home/users/ethan/example/`\n- `example`\n- `hello.txt`\n- `/home/users/ethan/example/hello.txt`\n\n## Συχνή παρανόηση\n\nΤο 66% διάλεξε `/home/users/ethan/example/`, δηλαδή τον κατάλογο (dirname) που περιέχει το αρχείο· το filepath όμως περιλαμβάνει και το όνομα του αρχείου.",
  "hint": "Το μονοπάτι πρέπει να προσδιορίζει μοναδικά *ποιο* αρχείο εννοούμε, όχι μόνο τον κατάλογο στον οποίο βρίσκεται."
 },
 {
  "id": "kahoot-find-seat-sorted",
  "kind": "kahoot",
  "title": "Αναζήτηση αριθμημένης θέσης σε αίθουσα",
  "source": {
   "title": "Kahoot «Δυαδική Αναζήτηση και Ταξινόμηση» (διάλεξη 17) και «Δυαδική Αναζήτηση, Ταξινόμηση, Πολυπλοκότητα και άλλα»",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   17,
   15
  ],
  "topics": [
   "searching",
   "complexity"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "O(log n)",
  "stats": {
   "responses": 101,
   "accuracy": 48
  },
  "label": "Κ17.7",
  "path": "questions/kahoot/kahoot-find-seat-sorted.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-find-seat-sorted.html",
  "statement": "Ψάχνω αν η αριθμημένη θέση μου J-13 υπάρχει (κάποιες λείπουν) στην αίθουσα προβολής N×N θέσεων. Χρειάζομαι τόσα βήματα:\n\n- O(n²)\n- O(log n)\n- O(2ⁿ)\n- 0 - μετά τον κόβιντ δεν έχει βγει ταινία της προκοπής\n\n## Συχνή παρανόηση\n\nΤο 33% επέλεξε O(n²), σαν να έπρεπε να ελέγξει κάθε θέση μία-μία. Επειδή όμως οι θέσεις είναι ταξινομημένες, δεν χρειάζεται να τις κοιτάξετε όλες.",
  "hint": "Οι θέσεις είναι αριθμημένες με σειρά (γραμμή και αριθμός)· σκεφτείτε ποιον αλγόριθμο αναζήτησης σας επιτρέπει αυτή η διάταξη."
 },
 {
  "id": "kahoot-first-index",
  "kind": "kahoot",
  "title": "Ο δείκτης του πρώτου στοιχείου",
  "source": {
   "title": "Kahoot «Πίνακες» (διάλεξη 10)",
   "years": [
    2025
   ]
  },
  "chapters": [
   10
  ],
  "topics": [
   "arrays"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "0",
  "stats": {
   "responses": 249,
   "accuracy": 82
  },
  "label": "Κ10.3",
  "path": "questions/kahoot/kahoot-first-index.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-first-index.html",
  "statement": "Το πρώτο στοιχείο ενός πίνακα με 10 στοιχεία βρίσκεται στη θέση (index):\n\n- `1`\n- `10`\n- `9`\n- `0`",
  "hint": "Ο δείκτης μετράει πόσα στοιχεία απέχουμε από την αρχή του πίνακα."
 },
 {
  "id": "kahoot-float-equality",
  "kind": "kahoot",
  "title": "Σύγκριση float με ==",
  "source": {
   "title": "Kahoot «Δεδομένα Εισόδου» (διάλεξη 9)",
   "years": [
    2025
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "floating-point",
   "good-practice"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "False",
  "stats": {
   "responses": 244,
   "accuracy": 94
  },
  "label": "Κ9.1",
  "path": "questions/kahoot/kahoot-float-equality.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-float-equality.html",
  "statement": "Είναι καλή ιδέα να ελέγχω `float`/`double` με τον τελεστή ισότητας (`==`);\n\n- True\n- False",
  "hint": "Σκεφτείτε αν αριθμοί όπως το 0.1 αναπαρίστανται ακριβώς στον υπολογιστή και τι σημαίνει αυτό για το αποτέλεσμα μιας σειράς πράξεων."
 },
 {
  "id": "kahoot-fopen-failure",
  "kind": "kahoot",
  "title": "Αποτυχία της fopen",
  "source": {
   "title": "Kahoot «Δομές + Αρχεία»",
   "years": [
    2025
   ]
  },
  "chapters": [
   18
  ],
  "topics": [
   "files"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "NULL",
  "stats": {
   "responses": 24,
   "accuracy": 50
  },
  "label": "Κ18.4",
  "path": "questions/kahoot/kahoot-fopen-failure.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-fopen-failure.html",
  "statement": "Η συνάρτηση `fopen` μόλις απέτυχε να ανοίξει ένα αρχείο. Επιστρέφει:\n\n- 1\n- -1\n- NULL\n- Τίποτα, απλά κρασάρει",
  "hint": "Η `fopen` επιστρέφει δείκτη σε `FILE`· ποια τιμή δείκτη σημαίνει «δεν δείχνω πουθενά»;"
 },
 {
  "id": "kahoot-for-break-overflow",
  "kind": "kahoot",
  "title": "for χωρίς συνθήκη με break",
  "source": {
   "title": "Kahoot «Ροή Ελέγχου #2» (διάλεξη 8)",
   "years": [
    2025
   ]
  },
  "chapters": [
   8
  ],
  "topics": [
   "loops",
   "control-flow",
   "integer-representation"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "Όταν υπερχειλίσει ο ακέραιος i",
  "stats": {
   "responses": 157,
   "accuracy": 36
  },
  "label": "Κ8.4",
  "path": "questions/kahoot/kahoot-for-break-overflow.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-for-break-overflow.html",
  "statement": "Θα τελειώσει αυτό το loop;\n\n```c\nfor (i = 1; ; i++)\n    if (i == 0)\n        break;\n```\n\n- Όχι δεν τελειώνει καθώς δεν έχει συνθήκη τερματισμού\n- Όταν υπερχειλίσει ο ακέραιος i\n- Όχι δεν τελειώνει καθώς ο ακέραιος i αρχικοποιείται στο 1 και αυξάνεται\n- Μόνο όταν λιώσει η CPU\n\n## Συχνή παρανόηση\n\nΤο 32% απάντησε ότι τελειώνει «μόνο όταν λιώσει η CPU», θεωρώντας ότι το `i` δεν θα γίνει ποτέ 0· όμως μετά τη μέγιστη τιμή του ο ακέραιος υπερχειλίζει σε αρνητικούς και φτάνει ξανά στο 0.",
  "hint": "Ένας `int` έχει πεπερασμένο εύρος τιμών· σκεφτείτε τι γίνεται αν συνεχίσουμε να τον αυξάνουμε πέρα από τη μέγιστη τιμή του."
 },
 {
  "id": "kahoot-for-empty-init",
  "kind": "kahoot",
  "title": "Η σύνταξη του for",
  "source": {
   "title": "Kahoot «Πίνακες» (διάλεξη 10)",
   "years": [
    2025
   ]
  },
  "chapters": [
   6
  ],
  "topics": [
   "loops"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "for(; i < 100; i++) printf(\"hello\\n\");",
  "stats": {
   "responses": 153,
   "accuracy": 59
  },
  "label": "Κ6.3",
  "path": "questions/kahoot/kahoot-for-empty-init.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-for-empty-init.html",
  "statement": "50% το κάνουν λάθος: αφού αρχικοποιήσω `i = 0;`, θέλω να τυπώσω hello 100 φορές. Κάνω:\n\n- `for(i < 100; i++;) printf(\"hello\\n\");`\n- `for(; i < 100; i++) printf(\"hello\\n\");`\n\n## Συχνή παρανόηση\n\nΤο 27% επέλεξε `for(i < 100; i++;)`, βάζοντας τη συνθήκη στη θέση της αρχικοποίησης. Τα τρία μέρη του `for` είναι πάντα αρχικοποίηση; συνθήκη; βήμα, και ένα κενό μέρος αφήνει μόνο το ερωτηματικό του.",
  "hint": "Η παρένθεση του `for` έχει τρία μέρη με σταθερή σειρά· αν ένα λείπει, μένει κενό αλλά το ερωτηματικό του μένει."
 },
 {
  "id": "kahoot-for-missing-increment",
  "kind": "kahoot",
  "title": "Ένα for χωρίς βήμα",
  "source": {
   "title": "Kahoot «Επίλυση Προβλημάτων» (διάλεξη 7)",
   "years": [
    2025
   ]
  },
  "chapters": [
   6
  ],
  "topics": [
   "loops"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "Όταν λιώσει η CPU",
  "stats": {
   "responses": 192,
   "accuracy": 56
  },
  "label": "Κ6.5",
  "path": "questions/kahoot/kahoot-for-missing-increment.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-for-missing-increment.html",
  "statement": "Πότε τελειώνει αυτό το loop;\n\n```c\nint i;\nfor (i = 0; i < 42; );\n```\n\n- Μετά από 2^32 επαναλήψεις\n- Όταν το i γίνει αρνητικό\n- Μετά από 42 επαναλήψεις\n- Όταν λιώσει η CPU",
  "hint": "Κοιτάξτε ποιο από τα τρία μέρη της `for` λείπει και αν κάτι άλλο μέσα στον βρόχο αλλάζει την τιμή του `i`."
 },
 {
  "id": "kahoot-for-n-times-trap",
  "kind": "kahoot",
  "title": "Πόσες φορές εκτελείται ένα for μέχρι N",
  "source": {
   "title": "Kahoot «Επίλυση Προβλημάτων» (διάλεξη 7), δύο εκδοχές",
   "years": [
    2025
   ]
  },
  "chapters": [
   6
  ],
  "topics": [
   "loops"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "Εξαρτάται",
  "stats": {
   "responses": 192,
   "accuracy": 23
  },
  "label": "Κ6.8",
  "path": "questions/kahoot/kahoot-for-n-times-trap.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-for-n-times-trap.html",
  "statement": "Πόσες φορές θα τυπώσει `hello` αυτό το loop;\n\n```c\nfor (int i = 0; i < N; i++)\n    printf(\"hello\\n\");\n```\n\n- N\n- N-1\n- N+1\n- Εξαρτάται\n\n## Συχνή παρανόηση\n\nΤο 34% απάντησε N, υποθέτοντας σιωπηρά ότι το `N` είναι θετικό· αν το `N` είναι 0 ή αρνητικό, το σώμα δεν εκτελείται καθόλου.",
  "hint": "Δεν ξέρουμε τίποτα για το `N`: δοκιμάστε νοερά τιμές όπως 5, 0 ή -3."
 },
 {
  "id": "kahoot-for-step-two",
  "kind": "kahoot",
  "title": "Επαναλήψεις με βήμα 2",
  "source": {
   "title": "Kahoot «Τελεστές, Εντολές και Ροή Ελέγχου» (διάλεξη 6)",
   "years": [
    2025
   ]
  },
  "chapters": [
   6
  ],
  "topics": [
   "loops"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "50 φορές",
  "stats": {
   "responses": 245,
   "accuracy": 57
  },
  "label": "Κ6.4",
  "path": "questions/kahoot/kahoot-for-step-two.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-for-step-two.html",
  "statement": "Το loop `int i; for (i = 0; i < 100; i += 2);` θα εκτελεστεί:\n\n- 100 φορές\n- 99 φορές\n- 49 φορές\n- 50 φορές\n\n## Συχνή παρανόηση\n\nΤο 27% επέλεξε 49 φορές, ένα κλασικό λάθος «κατά ένα» (off-by-one): ξεχνά ότι μετράει και η επανάληψη με `i = 0`.",
  "hint": "Γράψτε τις τιμές του `i` για τις οποίες εκτελείται το σώμα: από πού ξεκινά, πού σταματά και πόσες είναι."
 },
 {
  "id": "kahoot-function-definition-parts",
  "kind": "kahoot",
  "title": "Τα μέρη του ορισμού συνάρτησης",
  "source": {
   "title": "Kahoot «Τύπωμα και Συναρτήσεις» (διάλεξη 3)",
   "years": [
    2025
   ]
  },
  "chapters": [
   3
  ],
  "topics": [
   "functions"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "Ο τύπος επιστροφής, Το σώμα της συνάρτησης, Τα ορίσματα",
  "stats": {
   "responses": 190,
   "accuracy": 31
  },
  "label": "Κ3.7",
  "path": "questions/kahoot/kahoot-function-definition-parts.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-function-definition-parts.html",
  "statement": "Ποιο από τα παρακάτω είναι μέρος του ορισμού μιας συνάρτησης σε C; (Επιλέξτε όλες τις σωστές απαντήσεις.)\n\n- Ο τύπος επιστροφής\n- Το σώμα της συνάρτησης\n- Τα ορίσματα\n- Η συνολοθεωρία Cantor",
  "hint": "Γράψτε νοερά τον ορισμό μιας απλής συνάρτησης, π.χ. της `square`, και ονομάστε κάθε κομμάτι του από αριστερά προς τα δεξιά."
 },
 {
  "id": "kahoot-function-return-type",
  "kind": "kahoot",
  "title": "Ο τύπος επιστροφής μιας συνάρτησης",
  "source": {
   "title": "Kahoot «Τύπωμα και Συναρτήσεις» (διάλεξη 3)",
   "years": [
    2025
   ]
  },
  "chapters": [
   3
  ],
  "topics": [
   "functions",
   "types"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "double",
  "stats": {
   "responses": 190,
   "accuracy": 28
  },
  "label": "Κ3.8",
  "path": "questions/kahoot/kahoot-function-return-type.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-function-return-type.html",
  "statement": "Ποιος ο τύπος επιστροφής της συνάρτησης:\n\n```c\ndouble square(int x) { return x * x; }\n```\n\n- square\n- double\n- int\n- x\n\n## Συχνή παρανόηση\n\nΤο 25% επέλεξε `int`, μπερδεύοντας τον τύπο της παραμέτρου `x` με τον τύπο επιστροφής· η τιμή του `x * x` μετατρέπεται σε `double` κατά την επιστροφή.",
  "hint": "Ο τύπος επιστροφής γράφεται πριν από το όνομα της συνάρτησης· ό,τι βρίσκεται μέσα στις παρενθέσεις αφορά τις παραμέτρους."
 },
 {
  "id": "kahoot-gangnam-views",
  "kind": "kahoot",
  "title": "Ο μετρητής του Gangnam Style",
  "source": {
   "title": "Kahoot «Μεταβλητές και Μνήμη», «Μεταβλητές και Συναρτήσεις» (διάλεξη 2)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "types",
   "integer-representation"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "int",
  "stats": {
   "responses": 301,
   "accuracy": 41
  },
  "label": "Κ2.11",
  "path": "questions/kahoot/kahoot-gangnam-views.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-gangnam-views.html",
  "statement": "Όταν το Gangnam Style στο YouTube κόντευε τα 2 δις views, η Google άλλαξε τον τύπο των views. Τι τύπου ήταν αρχικά;\n\n- `char`\n- `double`\n- `int64_t`\n- `int`\n\n## Συχνή παρανόηση\n\nΤο 26% διάλεξε `int64_t`, που είναι ο τύπος στον οποίο μετέβη η Google *μετά*· ένας 64-bit ακέραιος δεν θα κόντευε ποτέ να υπερχειλίσει στα 2 δις.",
  "hint": "Ποιος από τους τύπους έχει μέγιστη τιμή κοντά στα 2 δισεκατομμύρια; Υπολογίστε το $2^{31}$."
 },
 {
  "id": "kahoot-getchar-257-values",
  "kind": "kahoot",
  "title": "Πόσες τιμές επιστρέφει η getchar",
  "source": {
   "title": "Kahoot «Δεδομένα Εισόδου» (διάλεξη 9)",
   "years": [
    2025
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output",
   "types"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "257",
  "stats": {
   "responses": 244,
   "accuracy": 18
  },
  "label": "Κ9.8",
  "path": "questions/kahoot/kahoot-getchar-257-values.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-getchar-257-values.html",
  "statement": "Πόσες διαφορετικές τιμές μπορεί να πάρει η τιμή επιστροφής της `getchar()`;\n\n- 0\n- 128\n- 256\n- 257\n\n## Συχνή παρανόηση\n\nΤο 64% επέλεξε 256, μετρώντας μόνο τις τιμές ενός byte και ξεχνώντας την επιπλέον τιμή `EOF`, που είναι και ο λόγος που η `getchar` επιστρέφει `int`.",
  "hint": "Μετρήστε πόσοι διαφορετικοί χαρακτήρες (bytes) μπορούν να διαβαστούν και μην ξεχάσετε ότι υπάρχει και μία ακόμη ειδική τιμή."
 },
 {
  "id": "kahoot-getchar-return-type",
  "kind": "kahoot",
  "title": "Ο τύπος επιστροφής της getchar",
  "source": {
   "title": "Kahoot «Δεδομένα Εισόδου» (διάλεξη 9) και «Πολυπλοκότητα και άλλα» (διάλεξη 15)",
   "years": [
    2025
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output",
   "types"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "int",
  "stats": {
   "responses": 368,
   "accuracy": 66
  },
  "label": "Κ9.5",
  "path": "questions/kahoot/kahoot-getchar-return-type.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-getchar-return-type.html",
  "statement": "Η συνάρτηση `getchar()` επιστρέφει μια τιμή τύπου:\n\n- int\n- double\n- char\n- Εξαρτάται",
  "hint": "Εκτός από κάθε δυνατό χαρακτήρα, η `getchar` πρέπει να μπορεί να επιστρέψει και μια ειδική τιμή για το τέλος της εισόδου."
 },
 {
  "id": "kahoot-git-commands",
  "kind": "kahoot",
  "title": "Ποιες είναι εντολές git;",
  "source": {
   "title": "Kahoot «Git και Τελεστές» (διάλεξη 4)",
   "years": [
    2025
   ]
  },
  "chapters": [
   4
  ],
  "topics": [
   "git"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "git push, git status, git commit",
  "stats": {
   "responses": 318,
   "accuracy": 34
  },
  "label": "Κ4.5",
  "path": "questions/kahoot/kahoot-git-commands.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-git-commands.html",
  "statement": "Ποιες από τις ακόλουθες είναι εντολές git; (Μπορεί να είναι σωστές περισσότερες από μία.)\n\n- `git push`\n- `git status`\n- `git gud`\n- `git commit`\n\n## Συχνή παρανόηση\n\nΤο 35% διάλεξε μόνο `git push` και `git commit`, ξεχνώντας το `git status`, που δεν αλλάζει τίποτα αλλά δείχνει ποια αρχεία έχουν αλλάξει ή είναι staged.",
  "hint": "Σκεφτείτε όχι μόνο τις εντολές που αλλάζουν το αποθετήριο, αλλά και εκείνη που τρέχουμε συνεχώς για να δούμε σε ποια κατάσταση βρίσκονται τα αρχεία μας."
 },
 {
  "id": "kahoot-git-forgot-commit",
  "kind": "kahoot",
  "title": "Ξέχασα κάτι στο git;",
  "source": {
   "title": "Kahoot «Ροή Ελέγχου #2» (διάλεξη 8)",
   "years": [
    2025
   ]
  },
  "chapters": [
   4
  ],
  "topics": [
   "git"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "git commit",
  "stats": {
   "responses": 157,
   "accuracy": 95
  },
  "label": "Κ4.1",
  "path": "questions/kahoot/kahoot-git-forgot-commit.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-git-forgot-commit.html",
  "statement": "Μόλις έγραψα το `trolley.c` και έκανα `git add` και μετά `git push`. Ξέχασα κάτι;\n\n- git branch\n- git out\n- git commit\n- Όχι, όλα καλά (τι είναι το git?)",
  "hint": "Το `git push` στέλνει στο GitHub ό,τι έχει καταγραφεί στο τοπικό ιστορικό· ποιο βήμα δημιουργεί αυτή την καταγραφή;"
 },
 {
  "id": "kahoot-git-order",
  "kind": "kahoot",
  "title": "Η σειρά των εντολών git",
  "source": {
   "title": "Kahoot «Git και Τελεστές» (διάλεξη 4)",
   "years": [
    2025
   ]
  },
  "chapters": [
   4
  ],
  "topics": [
   "git"
  ],
  "difficulty": 3,
  "type": "short-answer",
  "answer": "git clone, git add, git commit, git push",
  "stats": {
   "responses": 318,
   "accuracy": 34
  },
  "label": "Κ4.6",
  "path": "questions/kahoot/kahoot-git-order.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-git-order.html",
  "statement": "Βάλτε τις ακόλουθες εντολές σε χρονολογική σειρά:\n\n- `git push`\n- `git commit`\n- `git clone`\n- `git add`",
  "hint": "Ακολουθήστε τον κύκλο του git: πρώτα αποκτάτε αντίγραφο του αποθετηρίου, μετά ετοιμάζετε (stage) τις αλλαγές, τις καταγράφετε τοπικά και στο τέλος τις στέλνετε στο GitHub."
 },
 {
  "id": "kahoot-git-vs-github",
  "kind": "kahoot",
  "title": "Git και GitHub",
  "source": {
   "title": "Kahoot «Git και Τελεστές» (διάλεξη 4)",
   "years": [
    2025
   ]
  },
  "chapters": [
   4
  ],
  "topics": [
   "git"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "False",
  "stats": {
   "responses": 318,
   "accuracy": 82
  },
  "label": "Κ4.2",
  "path": "questions/kahoot/kahoot-git-vs-github.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-git-vs-github.html",
  "statement": "Το git και το GitHub είναι το ίδιο πράγμα.\n\n- True\n- False",
  "hint": "Το ένα είναι πρόγραμμα που τρέχει στον υπολογιστή σας, το άλλο μια υπηρεσία στο διαδίκτυο. Μπορεί να υπάρχει το ένα χωρίς το άλλο;"
 },
 {
  "id": "kahoot-global-declaration",
  "kind": "kahoot",
  "title": "Πού δηλώνονται οι παγκόσμιες μεταβλητές",
  "source": {
   "title": "Kahoot «Εμβέλεια, Μνήμη και Συμβολοσειρές» (διάλεξη 14)",
   "years": [
    2025
   ]
  },
  "chapters": [
   14
  ],
  "topics": [
   "scope"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "Έξω από οποιαδήποτε συνάρτηση",
  "stats": {
   "responses": 97,
   "accuracy": 93
  },
  "label": "Κ14.1",
  "path": "questions/kahoot/kahoot-global-declaration.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-global-declaration.html",
  "statement": "Οι μεταβλητές παγκόσμιας εμβέλειας (global scope) δηλώνονται:\n\n- Μέσα στην συνάρτηση main\n- Έξω από οποιαδήποτε συνάρτηση\n- Μέσα σε οποιαδήποτε συνάρτηση\n- Δεν υπάρχουν μεταβλητές παγκόσμιας εμβέλειας",
  "hint": "Η εμβέλεια καθορίζεται από το σημείο της δήλωσης· για να είναι ορατή από κάθε συνάρτηση, πού πρέπει να βρίσκεται η δήλωση;"
 },
 {
  "id": "kahoot-good-comment",
  "kind": "kahoot",
  "title": "Καλό σχόλιο;",
  "source": {
   "title": "Kahoot «Επίλυση Προβλημάτων» (διάλεξη 7)",
   "years": [
    2025
   ]
  },
  "chapters": [
   7
  ],
  "topics": [
   "good-practice"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "False",
  "stats": {
   "responses": 192,
   "accuracy": 61
  },
  "label": "Κ7.4",
  "path": "questions/kahoot/kahoot-good-comment.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-good-comment.html",
  "statement": "Αυτό είναι ένα παράδειγμα καλού σχολίου:\n\n```c\nprintf(\"Hello\"); // prints hello to the screen\n```\n\n- True\n- False\n\n## Συχνή παρανόηση\n\nΤο 34% απάντησε True· όμως ένα σχόλιο που επαναλαμβάνει τι κάνει ο κώδικας δεν προσθέτει τίποτα, ένα καλό σχόλιο εξηγεί το «γιατί».",
  "hint": "Ρωτήστε τον εαυτό σας τι πληροφορία προσθέτει το σχόλιο σε κάποιον που ήδη ξέρει να διαβάζει C."
 },
 {
  "id": "kahoot-goto-in-exam",
  "kind": "kahoot",
  "title": "goto στο διαγώνισμα",
  "source": {
   "title": "Kahoot «Ροή Ελέγχου #2» (διάλεξη 8)",
   "years": [
    2025
   ]
  },
  "chapters": [
   8
  ],
  "topics": [
   "control-flow",
   "good-practice"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "False",
  "stats": {
   "responses": 157,
   "accuracy": 97
  },
  "label": "Κ8.1",
  "path": "questions/kahoot/kahoot-goto-in-exam.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-goto-in-exam.html",
  "statement": "Είναι καλή ιδέα να χρησιμοποιήσω `goto` στο τελικό διαγώνισμα;\n\n- True\n- False",
  "hint": "Θυμηθείτε τι λέει ο δομημένος προγραμματισμός για τα άλματα σε ετικέτες."
 },
 {
  "id": "kahoot-heap-free-any",
  "kind": "kahoot",
  "title": "Αποδέσμευση από τον σωρό",
  "source": {
   "title": "Kahoot «Μνήμη» (διάλεξη 13)",
   "years": [
    2025
   ]
  },
  "chapters": [
   13
  ],
  "topics": [
   "dynamic-memory",
   "memory-model"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "οποιοδήποτε στοιχείο του σωρού",
  "stats": {
   "responses": 135,
   "accuracy": 67
  },
  "label": "Κ13.6",
  "path": "questions/kahoot/kahoot-heap-free-any.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-heap-free-any.html",
  "statement": "Όταν αποδεσμεύουμε τη μνήμη ενός στοιχείου από έναν σωρό, αυτό το στοιχείο είναι:\n\n- πάντα το τελευταίο που βάλαμε στον σωρό\n- πάντα το πρώτο που βάλαμε στον σωρό\n- οποιοδήποτε στοιχείο του σωρού\n- το 42ο στην σειρά",
  "hint": "Σε αντίθεση με τη στοίβα, ο σωρός δεν επιβάλλει σειρά· ποιος αποφασίζει πότε ελευθερώνεται κάτι;"
 },
 {
  "id": "kahoot-heap-not-contiguous",
  "kind": "kahoot",
  "title": "Είναι συνεχόμενος ο σωρός;",
  "source": {
   "title": "Kahoot «Δείκτες Παντού!» (διάλεξη 12) και «Μνήμη» (διάλεξη 13)",
   "years": [
    2025
   ]
  },
  "chapters": [
   13
  ],
  "topics": [
   "memory-model",
   "dynamic-memory"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "False",
  "stats": {
   "responses": 215,
   "accuracy": 75
  },
  "label": "Κ13.4",
  "path": "questions/kahoot/kahoot-heap-not-contiguous.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-heap-not-contiguous.html",
  "statement": "Τα στοιχεία του σωρού αποθηκεύονται σε μια συνεχόμενη περιοχή της μνήμης.\n\n- True\n- False",
  "hint": "Σκεφτείτε τι γίνεται όταν δεσμεύουμε και αποδεσμεύουμε κομμάτια με τυχαία σειρά."
 },
 {
  "id": "kahoot-homework-comments",
  "kind": "kahoot",
  "title": "Εργασία χωρίς σχόλια",
  "source": {
   "title": "Kahoot «Επίλυση Προβλημάτων» (διάλεξη 7)",
   "years": [
    2025
   ]
  },
  "chapters": [
   7
  ],
  "topics": [
   "good-practice"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "False",
  "stats": {
   "responses": 192,
   "accuracy": 71
  },
  "label": "Κ7.3",
  "path": "questions/kahoot/kahoot-homework-comments.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-homework-comments.html",
  "statement": "Θα βαθμολογηθεί η εργασία μου χωρίς σχόλια στον κώδικά μου;\n\n- True\n- False\n\n## Συχνή παρανόηση\n\nΤο 25% απάντησε True, θεωρώντας τα σχόλια προαιρετικά· στο μάθημα όμως τα σχόλια και η τεκμηρίωση είναι μέρος αυτού που βαθμολογείται.",
  "hint": "Θυμηθείτε τι είπαμε για τον σχολιασμό των προγραμμάτων και την ποιότητα του κώδικα που παραδίδετε."
 },
 {
  "id": "kahoot-if-else-trace",
  "kind": "kahoot",
  "title": "Απλό if-else",
  "source": {
   "title": "Kahoot «Τελεστές, Εντολές και Ροή Ελέγχου» (διάλεξη 6)",
   "years": [
    2025
   ]
  },
  "chapters": [
   6
  ],
  "topics": [
   "conditionals"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "World",
  "stats": {
   "responses": 245,
   "accuracy": 91
  },
  "label": "Κ6.1",
  "path": "questions/kahoot/kahoot-if-else-trace.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-if-else-trace.html",
  "statement": "Τι θα τυπώσει το ακόλουθο πρόγραμμα;\n\n```c\nint x = 42;\nif (x > 42)\n    printf(\"Hello\");\nelse\n    printf(\"World\");\n```\n\n- Hello\n- World\n- HelloWorld\n- Hello World",
  "hint": "Υπολογίστε τη συνθήκη `x > 42` για `x = 42` και θυμηθείτε ότι εκτελείται ακριβώς ένας από τους δύο κλάδους."
 },
 {
  "id": "kahoot-if-without-parens",
  "kind": "kahoot",
  "title": "if χωρίς παρενθέσεις",
  "source": {
   "title": "Kahoot «Τελεστές, Εντολές και Ροή Ελέγχου» (διάλεξη 6)",
   "years": [
    2025
   ]
  },
  "chapters": [
   6
  ],
  "topics": [
   "conditionals"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "False",
  "stats": {
   "responses": 245,
   "accuracy": 42
  },
  "label": "Κ6.6",
  "path": "questions/kahoot/kahoot-if-without-parens.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-if-without-parens.html",
  "statement": "Η εντολή `if x == 42 printf(\"Hello world\\n\");` είναι δεκτή στην C.\n\n- True\n- False\n\n## Συχνή παρανόηση\n\nΤο 53% απάντησε True, ίσως από γλώσσες όπως η Python· στην C η συνθήκη της `if` πρέπει να είναι σε παρενθέσεις.",
  "hint": "Θυμηθείτε ακριβώς τη σύνταξη της `if` όπως δόθηκε στη θεωρία: τι περιβάλλει τη συνθήκη;"
 },
 {
  "id": "kahoot-input-buffering",
  "kind": "kahoot",
  "title": "Φτάνουν αμέσως τα δεδομένα;",
  "source": {
   "title": "Kahoot «Δεδομένα Εισόδου» (διάλεξη 9)",
   "years": [
    2025
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "False",
  "stats": {
   "responses": 244,
   "accuracy": 82
  },
  "label": "Κ9.3",
  "path": "questions/kahoot/kahoot-input-buffering.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-input-buffering.html",
  "statement": "Τα δεδομένα που πληκτρολογούμε στέλνονται άμεσα στο πρόγραμμά μας.\n\n- True\n- False",
  "hint": "Σκεφτείτε τι ρόλο παίζει το πλήκτρο Enter όταν ένα πρόγραμμα περιμένει είσοδο από το πληκτρολόγιο."
 },
 {
  "id": "kahoot-int-array-address",
  "kind": "kahoot",
  "title": "Διεύθυνση στοιχείου πίνακα int",
  "source": {
   "title": "Kahoot «Πίνακες» (διάλεξη 10)",
   "years": [
    2025
   ]
  },
  "chapters": [
   10
  ],
  "topics": [
   "arrays",
   "memory-model"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "1168",
  "stats": {
   "responses": 249,
   "accuracy": 47
  },
  "label": "Κ10.8",
  "path": "questions/kahoot/kahoot-int-array-address.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-int-array-address.html",
  "statement": "Ο πίνακας `int numbers[200]` με `sizeof(int) == 4` ξεκινάει στη διεύθυνση 1000. Πού βρίσκεται το στοιχείο `numbers[42]`;\n\n- `1042`\n- `1046`\n- `1842`\n- `1168`",
  "hint": "Τα στοιχεία είναι συνεχόμενα στη μνήμη και το καθένα πιάνει `sizeof(int)` bytes."
 },
 {
  "id": "kahoot-int-array-bytes",
  "kind": "kahoot",
  "title": "Μέγεθος πίνακα int",
  "source": {
   "title": "Kahoot «Πίνακες» (διάλεξη 10)",
   "years": [
    2025
   ]
  },
  "chapters": [
   10,
   2
  ],
  "topics": [
   "arrays",
   "types",
   "memory-model"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "Εξαρτάται",
  "stats": {
   "responses": 249,
   "accuracy": 49
  },
  "label": "Κ10.7",
  "path": "questions/kahoot/kahoot-int-array-bytes.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-int-array-bytes.html",
  "statement": "Ένας πίνακας `int numbers[1024];` πόσα bytes καταλαμβάνει στη μνήμη;\n\n- `1024`\n- `4096`\n- `8192`\n- Εξαρτάται\n\n## Συχνή παρανόηση\n\nΤο 35% επέλεξε `4096`, θεωρώντας ότι ένας `int` είναι πάντα 4 bytes. Το πρότυπο της C δεν ορίζει το ακριβές μέγεθος του `int`· εξαρτάται από το σύστημα.",
  "hint": "Το μέγεθος του πίνακα είναι πλήθος στοιχείων × μέγεθος στοιχείου· είναι το μέγεθος του `int` ίδιο παντού;"
 },
 {
  "id": "kahoot-int-overflow-sign",
  "kind": "kahoot",
  "title": "Άθροισμα θετικών int",
  "source": {
   "title": "Kahoot «Μεταβλητές και Μνήμη», «Μεταβλητές και Συναρτήσεις» (διάλεξη 2)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "integer-representation",
   "types"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "Όχι",
  "stats": {
   "responses": 301,
   "accuracy": 87
  },
  "label": "Κ2.2",
  "path": "questions/kahoot/kahoot-int-overflow-sign.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-int-overflow-sign.html",
  "statement": "Αν προσθέσω δύο θετικούς αριθμούς τύπου `int`, το αποτέλεσμα είναι πάντα θετικό;\n\n- Ναι\n- Όχι",
  "hint": "Ο `int` έχει πεπερασμένο εύρος τιμών. Τι συμβαίνει όταν το άθροισμα ξεπεράσει τη μέγιστη τιμή του;"
 },
 {
  "id": "kahoot-int-size",
  "kind": "kahoot",
  "title": "Το μέγεθος του int",
  "source": {
   "title": "Kahoot «Μεταβλητές και Μνήμη», «Μεταβλητές και Συναρτήσεις» (διάλεξη 2)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "types"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "Εξαρτάται",
  "stats": {
   "responses": 301,
   "accuracy": 37
  },
  "label": "Κ2.13",
  "path": "questions/kahoot/kahoot-int-size.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-int-size.html",
  "statement": "Με πόσα bytes αναπαρίσταται ο τύπος `int` στη μνήμη;\n\n- 2\n- 4\n- 8\n- Εξαρτάται\n\n## Συχνή παρανόηση\n\nΤο 46% απάντησε 4, που είναι το συνηθισμένο μέγεθος στα σημερινά συστήματα, αλλά το πρότυπο της C δεν το ορίζει· σε άλλες αρχιτεκτονικές ο `int` μπορεί να είναι 2 bytes.",
  "hint": "Τι εγγυάται το πρότυπο της C για το μέγεθος του `int`; Γι' αυτό υπάρχουν το `sizeof` και οι τύποι του `stdint.h`."
 },
 {
  "id": "kahoot-ip-address-count",
  "kind": "kahoot",
  "title": "Πλήθος διευθύνσεων IPv4",
  "source": {
   "title": "Kahoot «Μεταβλητές και Μνήμη», «Μεταβλητές και Συναρτήσεις» (διάλεξη 2)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "computers",
   "integer-representation"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "4 δις",
  "stats": {
   "responses": 301,
   "accuracy": 57
  },
  "label": "Κ2.8",
  "path": "questions/kahoot/kahoot-ip-address-count.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-ip-address-count.html",
  "statement": "Με δεδομένο ότι μια IP address περιέχει 4 byte, πόσες IP διευθύνσεις μπορούν να υπάρξουν;\n\n- 1.101.101.10\n- 4 δις\n- $2^{16}$\n- 256.000\n\n## Συχνή παρανόηση\n\nΤο 25% απάντησε $2^{16}$, μετρώντας 16 bits αντί για 32 (4 bytes × 8 bits).",
  "hint": "Τα 4 bytes είναι συνολικά 32 bits. Πόσους διαφορετικούς συνδυασμούς δίνουν 32 bits, και πόσο είναι αυτό περίπου;"
 },
 {
  "id": "kahoot-ip-address-format",
  "kind": "kahoot",
  "title": "Η μορφή μιας IP διεύθυνσης",
  "source": {
   "title": "Kahoot «Μεταβλητές και Μνήμη», «Μεταβλητές και Συναρτήσεις» (διάλεξη 2)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "computers"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "1.1.1.1",
  "stats": {
   "responses": 301,
   "accuracy": 82
  },
  "label": "Κ2.4",
  "path": "questions/kahoot/kahoot-ip-address-format.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-ip-address-format.html",
  "statement": "Ποια από τα παρακάτω αντιστοιχεί σε ένα IP address;\n\n- 1.2.3\n- 1.1.1.1\n- A.B.C.D.E\n- hello world",
  "hint": "Μια διεύθυνση IPv4 γράφεται ως τέσσερις δεκαδικοί αριθμοί από 0 έως 255, χωρισμένοι με τελείες."
 },
 {
  "id": "kahoot-ip-octet-size",
  "kind": "kahoot",
  "title": "Πόσος χώρος για ένα κομμάτι IP",
  "source": {
   "title": "Kahoot «Μεταβλητές και Μνήμη», «Μεταβλητές και Συναρτήσεις» (διάλεξη 2)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "computers",
   "integer-representation"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "Ένα byte",
  "stats": {
   "responses": 301,
   "accuracy": 45
  },
  "label": "Κ2.10",
  "path": "questions/kahoot/kahoot-ip-octet-size.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-ip-octet-size.html",
  "statement": "Κάθε ένας από τους 4 αριθμούς μιας IP address είναι από το 0 μέχρι το 255. Για να αναπαρασταθεί κάθε ένας επαρκεί:\n\n- Ένα bit\n- Ένα byte\n- Ένας 32-bit αριθμός\n- Ένας 64-bit αριθμός",
  "hint": "Πόσες διαφορετικές τιμές χρειάζονται, και πόσες χωράνε σε $n$ bits; Βρείτε τη μικρότερη επιλογή που αρκεί."
 },
 {
  "id": "kahoot-large-array-placement",
  "kind": "kahoot",
  "title": "Πού βάζω έναν μεγάλο πίνακα",
  "source": {
   "title": "Kahoot «Δείκτες Παντού!» (διάλεξη 12) και «Μνήμη» (διάλεξη 13)",
   "years": [
    2025
   ]
  },
  "chapters": [
   13
  ],
  "topics": [
   "memory-model",
   "dynamic-memory",
   "arrays"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "Σωρό",
  "stats": {
   "responses": 215,
   "accuracy": 65
  },
  "label": "Κ13.8",
  "path": "questions/kahoot/kahoot-large-array-placement.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-large-array-placement.html",
  "statement": "Έχω να δημιουργήσω έναν μεγάλο πίνακα (10⁷ στοιχεία). Επιλέγω:\n\n- Στοίβα\n- Σωρό\n- Στίβο\n- Να μειώσω τον αριθμό των στοιχείων",
  "hint": "Θυμηθείτε πόσο μεγάλη είναι συνήθως η στοίβα (`ulimit -s`) σε σχέση με τη μνήμη που μπορεί να δώσει ο σωρός."
 },
 {
  "id": "kahoot-last-element",
  "kind": "kahoot",
  "title": "Το τελευταίο στοιχείο πίνακα",
  "source": {
   "title": "Kahoot «Πίνακες» (διάλεξη 10)",
   "years": [
    2025
   ]
  },
  "chapters": [
   10
  ],
  "topics": [
   "arrays"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "students[99]",
  "stats": {
   "responses": 249,
   "accuracy": 81
  },
  "label": "Κ10.4",
  "path": "questions/kahoot/kahoot-last-element.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-last-element.html",
  "statement": "Το τελευταίο στοιχείο ενός πίνακα με ορισμό `int students[100];` είναι:\n\n- `students[100]`\n- `students[101]`\n- `students[99]`\n- `students[-1]`",
  "hint": "Αν η αρίθμηση ξεκινά από το 0, ποιος είναι ο τελευταίος από 100 διαδοχικούς δείκτες;"
 },
 {
  "id": "kahoot-linear-vs-binary-search",
  "kind": "kahoot",
  "title": "Αναζήτηση σε μη ταξινομημένο πίνακα",
  "source": {
   "title": "Kahoot «Δυαδική Αναζήτηση και Ταξινόμηση» (διάλεξη 17) και «Δυαδική Αναζήτηση, Ταξινόμηση, Πολυπλοκότητα και άλλα»",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   17
  ],
  "topics": [
   "searching"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "Γραμμική Αναζήτηση",
  "stats": {
   "responses": 101,
   "accuracy": 85
  },
  "label": "Κ17.2",
  "path": "questions/kahoot/kahoot-linear-vs-binary-search.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-linear-vs-binary-search.html",
  "statement": "Ψάχνω να βρω ένα στοιχείο σε έναν μη ταξινομημένο πίνακα n θέσεων. Χρησιμοποιώ:\n\n- Γραμμική Αναζήτηση\n- Δυαδική Αναζήτηση",
  "hint": "Ρωτήστε τον εαυτό σας τι προϋπόθεση έχει ο καθένας από τους δύο αλγορίθμους για τη σειρά των στοιχείων."
 },
 {
  "id": "kahoot-linux-servers",
  "kind": "kahoot",
  "title": "Το ΛΣ των web servers",
  "source": {
   "title": "Kahoot «Command Line» (διάλεξη 1)",
   "years": [
    2025
   ]
  },
  "chapters": [
   1
  ],
  "topics": [
   "unix"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "Linux",
  "stats": {
   "responses": 209,
   "accuracy": 65
  },
  "label": "Κ1.6",
  "path": "questions/kahoot/kahoot-linux-servers.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-linux-servers.html",
  "statement": "Το λειτουργικό σύστημα που τρέχει το 90% των web servers σήμερα είναι το\n\n- Linux\n- Limux\n- MacOS\n- Windows",
  "hint": "Είναι το ίδιο ελεύθερο λειτουργικό σύστημα που χρησιμοποιούμε στα εργαστήρια του μαθήματος (προσοχή στην ορθογραφία των επιλογών)."
 },
 {
  "id": "kahoot-linux-unix",
  "kind": "kahoot",
  "title": "Η καταγωγή του Linux",
  "source": {
   "title": "Kahoot «Command Line» (διάλεξη 1)",
   "years": [
    2025
   ]
  },
  "chapters": [
   1
  ],
  "topics": [
   "unix"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "Unix",
  "stats": {
   "responses": 209,
   "accuracy": 87
  },
  "label": "Κ1.1",
  "path": "questions/kahoot/kahoot-linux-unix.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-linux-unix.html",
  "statement": "Το Linux είναι βασισμένο σε ένα λειτουργικό σύστημα που λέγεται\n\n- Multics\n- Simics\n- Unix\n- Κανένα από τα παραπάνω",
  "hint": "Το Linux είναι ένα λειτουργικό σύστημα «τύπου …»· σκεφτείτε από ποιο σύστημα των Bell Labs πήρε τη φιλοσοφία του."
 },
 {
  "id": "kahoot-list-insert-middle",
  "kind": "kahoot",
  "title": "Εισαγωγή στη μέση λίστας",
  "source": {
   "title": "Kahoot «Λίστες, Δέντρα and Beyond»",
   "years": [
    2025
   ]
  },
  "chapters": [
   21
  ],
  "topics": [
   "linked-lists",
   "complexity"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "O(n)",
  "stats": {
   "responses": 93,
   "accuracy": 39
  },
  "label": "Κ21.3",
  "path": "questions/kahoot/kahoot-list-insert-middle.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-list-insert-middle.html",
  "statement": "Η προσθήκη ενός στοιχείου στη μέση μιας απλά συνδεδεμένης λίστας γίνεται σε χρόνο:\n\n- O(n^2)\n- O(f(x))\n- O(n)\n- O(1)\n\n## Συχνή παρανόηση\n\nΤο 26% επέλεξε O(1), μετρώντας μόνο την αλλαγή των δύο δεικτών και ξεχνώντας ότι πρώτα πρέπει να φτάσουμε στη μέση διατρέχοντας τη λίστα από την αρχή (άλλο ένα 32% διάλεξε το αστείο O(f(x))).",
  "hint": "Σε μια απλά συνδεδεμένη λίστα έχετε μόνο τον δείκτη στην κεφαλή· πόσα βήματα χρειάζονται για να φτάσετε στη μέση;"
 },
 {
  "id": "kahoot-list-use-after-free",
  "kind": "kahoot",
  "title": "Ανάγνωση διαγραμμένου στοιχείου",
  "source": {
   "title": "Kahoot «Λίστες, Δέντρα and Beyond»",
   "years": [
    2025
   ]
  },
  "chapters": [
   21,
   13
  ],
  "topics": [
   "linked-lists",
   "dynamic-memory",
   "undefined-behavior"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "Το πρόγραμμά μου θα σκάσει (Segmentation Fault)",
  "stats": {
   "responses": 93,
   "accuracy": 92
  },
  "label": "Κ21.1",
  "path": "questions/kahoot/kahoot-list-use-after-free.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-list-use-after-free.html",
  "statement": "Μόλις διέγραψα ένα στοιχείο από μια λίστα. Τι θα συμβεί αν προσπαθήσω να το διαβάσω;\n\n- Το πρόγραμμά μου θα σκάσει (Segmentation Fault)\n- Όλα θα πάνε καλά και θα διαβάσω κανονικά το στοιχείο",
  "hint": "Μετά το `free` η μνήμη του κόμβου δεν ανήκει πια στο πρόγραμμά σας· σκεφτείτε αν είναι ασφαλές να τη διαβάσετε."
 },
 {
  "id": "kahoot-little-endian-read",
  "kind": "kahoot",
  "title": "Ανάγνωση int σε little endian",
  "source": {
   "title": "Kahoot «Δομές + Αρχεία»",
   "years": [
    2025
   ]
  },
  "chapters": [
   18,
   2
  ],
  "topics": [
   "files",
   "integer-representation"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "0xbeefcafe",
  "stats": {
   "responses": 24,
   "accuracy": 62
  },
  "label": "Κ18.2",
  "path": "questions/kahoot/kahoot-little-endian-read.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-little-endian-read.html",
  "statement": "Το αρχείο `input.txt` περιέχει τα bytes `0xfe 0xca 0xef 0xbe`. Αν διαβάσουμε έναν `int` σε μορφή little endian, θα πάρουμε:\n\n- 0xfecaefbe\n- 0xefbefeca\n- 0xbeefcafe\n- 0xcafebeef",
  "hint": "Στο little endian το πρώτο byte στη μνήμη (ή στο αρχείο) είναι το λιγότερο σημαντικό byte του αριθμού."
 },
 {
  "id": "kahoot-local-variable-storage",
  "kind": "kahoot",
  "title": "Πού αποθηκεύονται οι τοπικές μεταβλητές",
  "source": {
   "title": "Kahoot «Εμβέλεια, Μνήμη και Συμβολοσειρές» (διάλεξη 14)",
   "years": [
    2025
   ]
  },
  "chapters": [
   14,
   13
  ],
  "topics": [
   "memory-model",
   "scope"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "Στην στοίβα ή στην στατική μνήμη ανάλογα με το αν δηλώθηκε static",
  "stats": {
   "responses": 97,
   "accuracy": 23
  },
  "label": "Κ14.8",
  "path": "questions/kahoot/kahoot-local-variable-storage.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-local-variable-storage.html",
  "statement": "Πού αποθηκεύονται οι τοπικές μεταβλητές μιας συνάρτησης;\n\n- Στην στοίβα\n- Στον σωρό\n- Στην στατική μνήμη\n- Στην στοίβα ή στην στατική μνήμη ανάλογα με το αν δηλώθηκε static\n\n## Συχνή παρανόηση\n\nΤο 55% απάντησε «Στην στοίβα», ξεχνώντας τις τοπικές `static` μεταβλητές, που έχουν τοπική εμβέλεια αλλά ζουν στη στατική μνήμη για όλη την εκτέλεση.",
  "hint": "Μια τοπική μεταβλητή μπορεί να κρατά την τιμή της από κλήση σε κλήση· σκεφτείτε ποια λέξη-κλειδί το κάνει αυτό και πού πρέπει να ζει μια τέτοια μεταβλητή."
 },
 {
  "id": "kahoot-malloc-doubles",
  "kind": "kahoot",
  "title": "Δέσμευση 10⁹ double",
  "source": {
   "title": "Kahoot «Δείκτες Παντού!» (διάλεξη 12) και «Μνήμη» (διάλεξη 13)",
   "years": [
    2025
   ]
  },
  "chapters": [
   13
  ],
  "topics": [
   "dynamic-memory",
   "types",
   "memory-model"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "double * array = malloc(1000000000 * sizeof(double));",
  "stats": {
   "responses": 215,
   "accuracy": 66
  },
  "label": "Κ13.7",
  "path": "questions/kahoot/kahoot-malloc-doubles.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-malloc-doubles.html",
  "statement": "Θέλω να αποθηκεύσω 10⁹ στοιχεία `double`. Τι κάνω;\n\n- `int * array = malloc(1000000000);`\n- `double array[1000000000];`\n- `double * array = malloc(1000000000);`\n- `double * array = malloc(1000000000 * sizeof(double));`",
  "hint": "Η `malloc` μετράει σε bytes, όχι σε στοιχεία· και θυμηθείτε πόσο χωράει η στοίβα."
 },
 {
  "id": "kahoot-malloc-int-array",
  "kind": "kahoot",
  "title": "malloc για πίνακα 10000 int",
  "source": {
   "title": "Kahoot «Ταξινόμηση και Δομές»",
   "years": [
    2025
   ]
  },
  "chapters": [
   13
  ],
  "topics": [
   "dynamic-memory"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "int * array = malloc(40000);",
  "stats": {
   "responses": 127,
   "accuracy": 60
  },
  "label": "Κ13.9",
  "path": "questions/kahoot/kahoot-malloc-int-array.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-malloc-int-array.html",
  "statement": "Έστω ότι οι `int` θέλουν 4 bytes για την αναπαράστασή τους. Για να δεσμεύσω μνήμη για έναν πίνακα 10000 `int` κάνω:\n\n- `int * array = malloc(10000);`\n- `int * array = malloc(4);`\n- `int * array = malloc(40000);`\n- Εξαρτάται",
  "hint": "Σε τι μονάδες μετράει το όρισμα της `malloc`; (Στον δικό σας κώδικα, γράψτε το με `sizeof`.)"
 },
 {
  "id": "kahoot-malloc-may-fail",
  "kind": "kahoot",
  "title": "Πάντα πετυχαίνει η malloc;",
  "source": {
   "title": "Kahoot «Δείκτες Παντού!» (διάλεξη 12) και «Μνήμη» (διάλεξη 13)",
   "years": [
    2025
   ]
  },
  "chapters": [
   13
  ],
  "topics": [
   "dynamic-memory",
   "memory-model"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "False",
  "stats": {
   "responses": 215,
   "accuracy": 70
  },
  "label": "Κ13.5",
  "path": "questions/kahoot/kahoot-malloc-may-fail.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-malloc-may-fail.html",
  "statement": "Έχω 16KB ελεύθερη μνήμη και τρέχω `malloc(8000)`: αυτή η κλήση σίγουρα θα πετύχει.\n\n- True\n- False",
  "hint": "Η ελεύθερη μνήμη δεν είναι απαραίτητα ένα ενιαίο κομμάτι, και γι' αυτό ελέγχουμε πάντα την τιμή επιστροφής."
 },
 {
  "id": "kahoot-man-command",
  "kind": "kahoot",
  "title": "Η εντολή man",
  "source": {
   "title": "Kahoot «Τύπωμα και Συναρτήσεις» (διάλεξη 3)",
   "years": [
    2025
   ]
  },
  "chapters": [
   1
  ],
  "topics": [
   "shell",
   "unix"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "man",
  "stats": {
   "responses": 190,
   "accuracy": 72
  },
  "label": "Κ1.3",
  "path": "questions/kahoot/kahoot-man-command.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-man-command.html",
  "statement": "Ποια εντολή τρέχω για να βρω τι κάνει ένα πρόγραμμα στο σύστημά μου;\n\n- cat\n- man\n- woman\n- tac",
  "hint": "Ψάχνουμε το εγχειρίδιο (manual) του προγράμματος· η εντολή είναι συντομογραφία αυτής της λέξης."
 },
 {
  "id": "kahoot-matrix-multiplication",
  "kind": "kahoot",
  "title": "Πολυπλοκότητα πολλαπλασιασμού πινάκων",
  "source": {
   "title": "Kahoot «Δυαδική Αναζήτηση, Ταξινόμηση, Πολυπλοκότητα και άλλα» και «Πολυπλοκότητα και άλλα» (διάλεξη 15)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   15,
   12
  ],
  "topics": [
   "complexity",
   "multidim-arrays"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "O(n³)",
  "stats": {
   "responses": 154,
   "accuracy": 49
  },
  "label": "Κ15.4",
  "path": "questions/kahoot/kahoot-matrix-multiplication.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-matrix-multiplication.html",
  "statement": "Μια συνάρτηση πολλαπλασιάζει δύο πίνακες `m1`, `m2` διαστάσεων N × N (με τον συνήθη αλγόριθμο, γραμμή επί στήλη). Η χρονική πολυπλοκότητά της είναι:\n\n- O(n²)\n- O(n!)\n- O(n)\n- O(τρέχα γύρευε)\n- O(log n)\n- O(n³)\n\n## Συχνή παρανόηση\n\nΤο 23% επέλεξε O(n²), μετρώντας μόνο τα N² στοιχεία του αποτελέσματος και όχι το εσωτερικό άθροισμα N γινομένων για το καθένα.",
  "hint": "Μετρήστε πόσα στοιχεία έχει ο πίνακας-αποτέλεσμα και πόσους πολλαπλασιασμούς χρειάζεται ο υπολογισμός του καθενός."
 },
 {
  "id": "kahoot-memory-categories",
  "kind": "kahoot",
  "title": "Κατηγορίες μνήμης",
  "source": {
   "title": "Kahoot «Δείκτες Παντού!» (διάλεξη 12) και «Μνήμη» (διάλεξη 13)",
   "years": [
    2025
   ]
  },
  "chapters": [
   13,
   14
  ],
  "topics": [
   "memory-model",
   "scope"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "False",
  "stats": {
   "responses": 215,
   "accuracy": 87
  },
  "label": "Κ13.2",
  "path": "questions/kahoot/kahoot-memory-categories.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-memory-categories.html",
  "statement": "Υπάρχουν μόνο δύο κατηγορίες μνήμης: η στοίβα και ο σωρός.\n\n- True\n- False",
  "hint": "Πού αποθηκεύονται οι παγκόσμιες μεταβλητές και τα string literals;"
 },
 {
  "id": "kahoot-memory-functions",
  "kind": "kahoot",
  "title": "malloc, calloc, realloc και free",
  "source": {
   "title": "Kahoot «Μνήμη» (διάλεξη 13)",
   "years": [
    2025
   ]
  },
  "chapters": [
   13
  ],
  "topics": [
   "dynamic-memory",
   "memory-model"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "Αλλάζω το μέγεθος δεσμευμένης μνήμης στον σωρό με την realloc, Η calloc είναι σαν την malloc απλά μηδενίζει τα στοιχεία της μνήμης",
  "stats": {
   "responses": 135,
   "accuracy": 27
  },
  "label": "Κ13.10",
  "path": "questions/kahoot/kahoot-memory-functions.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-memory-functions.html",
  "statement": "Επιλέξτε όλα όσα είναι σωστά.\n\n- Αποδεσμεύω μνήμη στην στοίβα με την free\n- Αλλάζω το μέγεθος δεσμευμένης μνήμης στον σωρό με την realloc\n- Η calloc είναι σαν την malloc απλά μηδενίζει τα στοιχεία της μνήμης\n- Η malloc μπορεί να σμικρύνει την μνήμη στην οποία δείχνει ένας δείκτης\n\n## Συχνή παρανόηση\n\nΠερίπου οι μισοί (50%) συμπεριέλαβαν ότι αποδεσμεύουμε μνήμη της στοίβας με την `free`. Η `free` είναι μόνο για μνήμη του σωρού· οι τοπικές μεταβλητές αποδεσμεύονται αυτόματα όταν επιστρέφει η συνάρτηση.",
  "hint": "Ποια μνήμη διαχειριζόμαστε εμείς με τις συναρτήσεις της `stdlib.h`, και ποια αποδεσμεύεται αυτόματα;"
 },
 {
  "id": "kahoot-msb-mask",
  "kind": "kahoot",
  "title": "Απομόνωση του πιο σημαντικού bit",
  "source": {
   "title": "Kahoot «Git και Τελεστές» (διάλεξη 4)",
   "years": [
    2025
   ]
  },
  "chapters": [
   4,
   5
  ],
  "topics": [
   "bitwise"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "byte & 0x80",
  "stats": {
   "responses": 318,
   "accuracy": 14
  },
  "label": "Κ4.9",
  "path": "questions/kahoot/kahoot-msb-mask.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-msb-mask.html",
  "statement": "Google backend engineer interview question: πώς απομονώνουμε το πιο σημαντικό bit (το 8ο) σε ένα byte;\n\n- `byte & 0xFF`\n- `byte & 0x80`\n- `byte | 0xFF`\n- `byte | 0x80`\n\n## Συχνή παρανόηση\n\nΤο 29% διάλεξε `byte & 0xFF`: η μάσκα `0xFF` έχει και τα 8 bits στο 1, άρα κρατάει ολόκληρο το byte αντί να απομονώνει μόνο το πιο σημαντικό.",
  "hint": "Γράψτε κάθε μάσκα στο δυαδικό. Για να κρατήσουμε ένα bit και να μηδενίσουμε τα υπόλοιπα, χρειαζόμαστε τον τελεστή που δίνει 1 μόνο όπου *και τα δύο* bits είναι 1, και μια μάσκα με ένα μόνο 1."
 },
 {
  "id": "kahoot-nested-index",
  "kind": "kahoot",
  "title": "Δείκτης μέσα σε δείκτη",
  "source": {
   "title": "Kahoot «Πίνακες» (διάλεξη 10)",
   "years": [
    2025
   ]
  },
  "chapters": [
   10
  ],
  "topics": [
   "arrays"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "1",
  "stats": {
   "responses": 249,
   "accuracy": 69
  },
  "label": "Κ10.6",
  "path": "questions/kahoot/kahoot-nested-index.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-nested-index.html",
  "statement": "Τι θα τυπώσει ο παρακάτω κώδικας;\n\n```c\nint a[] = {5, 4, 3, 1, 2, 6};\nprintf(\"%d\\n\", a[ a[2] ]);\n```\n\n- `1`\n- `4`\n- `3`\n- `6`",
  "hint": "Υπολογίστε πρώτα την εσωτερική έκφραση και χρησιμοποιήστε το αποτέλεσμα ως θέση."
 },
 {
  "id": "kahoot-node-binary-tree",
  "kind": "kahoot",
  "title": "Κόμβος με left και right",
  "source": {
   "title": "Kahoot «Προχωρημένες Δομές #2»",
   "years": [
    2025
   ]
  },
  "chapters": [
   20,
   21
  ],
  "topics": [
   "structs",
   "trees"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "binary tree (δυαδικό δέντρο)",
  "stats": {
   "responses": 58,
   "accuracy": 67
  },
  "label": "Κ20.1",
  "path": "questions/kahoot/kahoot-node-binary-tree.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-node-binary-tree.html",
  "statement": "Η δομή `struct node {int x; struct node *left; struct node *right;}` αντιστοιχεί σε:\n\n- single linked list (απλά συνδεδεμένη λίστα)\n- cyclic graph (κυκλικός γράφος)\n- binary tree (δυαδικό δέντρο)\n- bitfield (πεδίο δυφίων)",
  "hint": "Μετρήστε πόσους δείκτες προς άλλους κόμβους έχει κάθε κόμβος και τι δηλώνουν τα ονόματά τους."
 },
 {
  "id": "kahoot-node-linked-list",
  "kind": "kahoot",
  "title": "Κόμβος με next",
  "source": {
   "title": "Kahoot «Προχωρημένες Δομές #2»",
   "years": [
    2025
   ]
  },
  "chapters": [
   20,
   21
  ],
  "topics": [
   "structs",
   "linked-lists"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "single linked list (απλά συνδεδεμένη λίστα)",
  "stats": {
   "responses": 58,
   "accuracy": 52
  },
  "label": "Κ20.5",
  "path": "questions/kahoot/kahoot-node-linked-list.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-node-linked-list.html",
  "statement": "Το `struct node {int x; struct node *next;}` είναι δομικό στοιχείο για:\n\n- union (ένωση)\n- binary tree (δυαδικό δέντρο)\n- single linked list (απλά συνδεδεμένη λίστα)\n- graph (γράφος)",
  "hint": "Κάθε κόμβος δείχνει σε έναν μόνο επόμενο κόμβο· τι σχήμα φτιάχνουν τέτοιοι κόμβοι αν τους αλυσοδέσετε;"
 },
 {
  "id": "kahoot-null-is-zero",
  "kind": "kahoot",
  "title": "Η τιμή του NULL",
  "source": {
   "title": "Kahoot «Δείκτες και Αναδρομή» (διάλεξη 11) και «Δείκτες Παντού!» (διάλεξη 12)",
   "years": [
    2025
   ]
  },
  "chapters": [
   11
  ],
  "topics": [
   "pointers"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "True",
  "stats": {
   "responses": 232,
   "accuracy": 65
  },
  "label": "Κ11.4",
  "path": "questions/kahoot/kahoot-null-is-zero.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-null-is-zero.html",
  "statement": "Η τιμή δείκτη `NULL` στα περισσότερα σημερινά συστήματα ισούται με τον αριθμό 0.\n\n- True\n- False\n\n## Συχνή παρανόηση\n\nΤο 28% απάντησε False, θεωρώντας το `NULL` ειδική τιμή χωρίς αριθμητική αναπαράσταση. Στην πράξη το `NULL` είναι η διεύθυνση 0.",
  "hint": "Ένας δείκτης είναι μια διεύθυνση, δηλαδή ένας αριθμός· ποια διεύθυνση διαλέξαμε να σημαίνει «πουθενά»;"
 },
 {
  "id": "kahoot-num-divisible-3-31",
  "kind": "kahoot",
  "title": "Ποιος αριθμός ικανοποιεί τη συνθήκη",
  "source": {
   "title": "Kahoot «Επίλυση Προβλημάτων» (διάλεξη 7)",
   "years": [
    2025
   ]
  },
  "chapters": [
   5
  ],
  "topics": [
   "operators"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "93",
  "stats": {
   "responses": 192,
   "accuracy": 58
  },
  "label": "Κ5.2",
  "path": "questions/kahoot/kahoot-num-divisible-3-31.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-num-divisible-3-31.html",
  "statement": "Ποιος αριθμός `num` κάνει την ακόλουθη έκφραση αληθή;\n\n```c\n(num > 10) && (num < 100) && (num % 3 == 0) && (num % 31 == 0)\n```\n\n- 3\n- 31\n- 42\n- 93",
  "hint": "Με το `&&` πρέπει να ισχύουν και οι τέσσερις συνθήκες ταυτόχρονα· ελέγξτε κάθε επιλογή μία προς μία."
 },
 {
  "id": "kahoot-or-combine",
  "kind": "kahoot",
  "title": "0xbeef | 0xcafe0000",
  "source": {
   "title": "Kahoot «Git και Τελεστές» (διάλεξη 4)",
   "years": [
    2025
   ]
  },
  "chapters": [
   4,
   5
  ],
  "topics": [
   "bitwise"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "0xcafebeef",
  "stats": {
   "responses": 318,
   "accuracy": 29
  },
  "label": "Κ4.7",
  "path": "questions/kahoot/kahoot-or-combine.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-or-combine.html",
  "statement": "Ποια η τιμή της παράστασης `0xbeef | 0xcafe0000`;\n\n- `0xffffffff`\n- `0xcafebeef`\n- `0xbeefcafe`\n- `0x00000000`\n\n## Συχνή παρανόηση\n\nΤο 29% απάντησε `0xbeefcafe`, διαβάζοντας το OR σαν «παράθεση με τη σειρά που γράφονται»· όμως το OR δεν μετακινεί bits, το καθένα μένει στη θέση του, και το `0xcafe` βρίσκεται στα πάνω 16 bits.",
  "hint": "Κάθε δεκαεξαδικό ψηφίο είναι 4 bits. Τα δύο νούμερα έχουν μη μηδενικά ψηφία σε διαφορετικές θέσεις· τι κάνει το OR όταν σε κάθε θέση ο ένας από τους δύο είναι 0;"
 },
 {
  "id": "kahoot-or-mask-ff",
  "kind": "kahoot",
  "title": "0xFF | 0x42",
  "source": {
   "title": "Kahoot «Git και Τελεστές» (διάλεξη 4)",
   "years": [
    2025
   ]
  },
  "chapters": [
   4
  ],
  "topics": [
   "bitwise"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "0xFF",
  "stats": {
   "responses": 318,
   "accuracy": 57
  },
  "label": "Κ4.3",
  "path": "questions/kahoot/kahoot-or-mask-ff.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-or-mask-ff.html",
  "statement": "Ποια η τιμή της παράστασης `0xFF | 0x42`;\n\n- `0xFF`\n- `42`\n- `0x42`\n- `1`",
  "hint": "Γράψτε και τους δύο αριθμούς στο δυαδικό. Αν ο ένας τελεστέος έχει ήδη 1 σε κάθε θέση, τι μπορεί να αλλάξει το bitwise OR;"
 },
 {
  "id": "kahoot-out-of-bounds",
  "kind": "kahoot",
  "title": "Πρόσβαση εκτός ορίων",
  "source": {
   "title": "Kahoot «Πίνακες» (διάλεξη 10)",
   "years": [
    2025
   ]
  },
  "chapters": [
   10
  ],
  "topics": [
   "arrays",
   "undefined-behavior"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "False",
  "stats": {
   "responses": 249,
   "accuracy": 85
  },
  "label": "Κ10.1",
  "path": "questions/kahoot/kahoot-out-of-bounds.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-out-of-bounds.html",
  "statement": "Δεν υπάρχει πρόβλημα αν προσπελάσω στοιχεία εκτός των ορίων ενός πίνακα.\n\n- True\n- False",
  "hint": "Ελέγχει η C τα όρια ενός πίνακα; Τι υπάρχει στη μνήμη αμέσως μετά το τελευταίο στοιχείο;"
 },
 {
  "id": "kahoot-perfect-tree-leaves",
  "kind": "kahoot",
  "title": "Φύλλα τέλειου δυαδικού δέντρου",
  "source": {
   "title": "Kahoot «Λίστες, Δέντρα and Beyond»",
   "years": [
    2025
   ]
  },
  "chapters": [
   22
  ],
  "topics": [
   "trees"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "~n/2",
  "stats": {
   "responses": 93,
   "accuracy": 45
  },
  "label": "Κ22.6",
  "path": "questions/kahoot/kahoot-perfect-tree-leaves.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-perfect-tree-leaves.html",
  "statement": "Έχω ένα τέλειο δυαδικό δέντρο με n κόμβους. Πόσα φύλλα έχει;\n\n- ~2n\n- ~n\n- ~n/2\n- Εξαρτάται",
  "hint": "Συγκρίνετε το πλήθος των κόμβων του τελευταίου επιπέδου με το άθροισμα όλων των προηγούμενων επιπέδων."
 },
 {
  "id": "kahoot-perfect-tree-nodes",
  "kind": "kahoot",
  "title": "Κόμβοι τέλειου δυαδικού δέντρου",
  "source": {
   "title": "Kahoot «Λίστες, Δέντρα and Beyond»",
   "years": [
    2025
   ]
  },
  "chapters": [
   22
  ],
  "topics": [
   "trees",
   "complexity"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "~2^n",
  "stats": {
   "responses": 93,
   "accuracy": 81
  },
  "label": "Κ22.1",
  "path": "questions/kahoot/kahoot-perfect-tree-nodes.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-perfect-tree-nodes.html",
  "statement": "Έχω ένα τέλειο δυαδικό δέντρο βάθους n. Πόσους κόμβους έχει;\n\n- ~n\n- ~log n\n- ~2^n\n- Εξαρτάται",
  "hint": "Μετρήστε τους κόμβους ανά επίπεδο: κάθε επίπεδο έχει διπλάσιους κόμβους από το προηγούμενο."
 },
 {
  "id": "kahoot-pointer-addition",
  "kind": "kahoot",
  "title": "Άθροισμα δύο δεικτών",
  "source": {
   "title": "Kahoot «Δείκτες και Αναδρομή» (διάλεξη 11) και «Δείκτες Παντού!» (διάλεξη 12)",
   "years": [
    2025
   ]
  },
  "chapters": [
   11
  ],
  "topics": [
   "pointers",
   "pointer-arithmetic"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "Μη δεκτή στην C",
  "stats": {
   "responses": 232,
   "accuracy": 28
  },
  "label": "Κ11.13",
  "path": "questions/kahoot/kahoot-pointer-addition.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-pointer-addition.html",
  "statement": "Έστω ότι `int *p, *q` είναι δύο δείκτες και ο καθένας έχει τιμή 42. Τότε η παράσταση `p + q` είναι:\n\n- `84`\n- `166`\n- Μη δεκτή στην C\n- `0`\n\n## Συχνή παρανόηση\n\nΤο 28% επέλεξε `166` και το 22% `84`, θεωρώντας ότι δύο δείκτες προστίθενται σαν ακέραιοι. Η C επιτρέπει δείκτη ± ακέραιο και διαφορά δύο δεικτών, όχι όμως άθροισμα δεικτών.",
  "hint": "Σκεφτείτε ποιες πράξεις ανάμεσα σε δείκτες και ακεραίους έχουν νόημα για μια διεύθυνση μνήμης."
 },
 {
  "id": "kahoot-pointer-increment-scalar",
  "kind": "kahoot",
  "title": "Αύξηση του ίδιου του δείκτη",
  "source": {
   "title": "Kahoot «Δείκτες και Αναδρομή» (διάλεξη 11) και «Δείκτες Παντού!» (διάλεξη 12)",
   "years": [
    2025
   ]
  },
  "chapters": [
   11
  ],
  "topics": [
   "pointers",
   "pointer-arithmetic",
   "undefined-behavior"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "Που να ξέρω",
  "stats": {
   "responses": 232,
   "accuracy": 37
  },
  "label": "Κ11.9",
  "path": "questions/kahoot/kahoot-pointer-increment-scalar.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-pointer-increment-scalar.html",
  "statement": "Τι θα τυπώσει ο παρακάτω κώδικας;\n\n```c\nint x = 41;\nint *ptr = &x;\nptr++;\nprintf(\"%d\", *ptr);\n```\n\n- `41`\n- `42`\n- `43`\n- Που να ξέρω\n\n## Συχνή παρανόηση\n\nΤο 25% επέλεξε `42`, θεωρώντας ότι το `ptr++` αυξάνει την τιμή του `x`. Στην πραγματικότητα αλλάζει τη διεύθυνση που κρατά ο δείκτης, όχι την τιμή στην οποία δείχνει.",
  "hint": "Μετά το `ptr++` πού δείχνει ο `ptr`; Υπάρχει εκεί κάποια μεταβλητή που ξέρουμε;"
 },
 {
  "id": "kahoot-pointer-plus-int-hex",
  "kind": "kahoot",
  "title": "Δείκτης συν 4 σε δεκαεξαδικό",
  "source": {
   "title": "Kahoot «Δείκτες και Αναδρομή» (διάλεξη 11)",
   "years": [
    2025
   ]
  },
  "chapters": [
   11,
   2
  ],
  "topics": [
   "pointer-arithmetic",
   "pointers"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "0x52",
  "stats": {
   "responses": 152,
   "accuracy": 31
  },
  "label": "Κ11.12",
  "path": "questions/kahoot/kahoot-pointer-plus-int-hex.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-pointer-plus-int-hex.html",
  "statement": "Έστω ότι `sizeof(int) == 4` και η τιμή του `int *ptr` είναι `0x42`. Ποια η τιμή της έκφρασης `ptr + 4`;\n\n- `0x46`\n- `42`\n- `0x52`\n- `0x4C`\n\n## Συχνή παρανόηση\n\nΤο 32% επέλεξε `0x4C` και το 22% `0x46`. Οι δεύτεροι ξέχασαν ότι το `+ 4` σημαίνει 4 × `sizeof(int)` bytes, ενώ οι πρώτοι πρόσθεσαν σωστά 16 bytes, αλλά μπέρδεψαν τη δεκαεξαδική πρόσθεση (16 = `0x10`).",
  "hint": "Η αριθμητική δεικτών μετράει σε στοιχεία, όχι σε bytes· προσέξτε και σε ποια βάση κάνετε την πρόσθεση."
 },
 {
  "id": "kahoot-pointer-plus-one",
  "kind": "kahoot",
  "title": "Η τιμή του ptr + 1",
  "source": {
   "title": "Kahoot «Δείκτες και Αναδρομή» (διάλεξη 11)",
   "years": [
    2025
   ]
  },
  "chapters": [
   11
  ],
  "topics": [
   "pointer-arithmetic",
   "types"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "Εξαρτάται",
  "stats": {
   "responses": 152,
   "accuracy": 61
  },
  "label": "Κ11.5",
  "path": "questions/kahoot/kahoot-pointer-plus-one.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-pointer-plus-one.html",
  "statement": "Έστω ότι η τιμή του δείκτη `int *ptr` είναι 42. Η τιμή του δείκτη `(ptr + 1)` είναι:\n\n- `43`\n- `46`\n- `42`\n- Εξαρτάται",
  "hint": "Πόσα bytes προχωράει ένας δείκτης σε `int` όταν του προσθέτουμε 1, και είναι αυτό το ίδιο σε κάθε σύστημα;"
 },
 {
  "id": "kahoot-pointer-size",
  "kind": "kahoot",
  "title": "Μέγεθος δεικτών",
  "source": {
   "title": "Kahoot «Δείκτες και Αναδρομή» (διάλεξη 11)",
   "years": [
    2025
   ]
  },
  "chapters": [
   11
  ],
  "topics": [
   "pointers",
   "types",
   "memory-model"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "True",
  "stats": {
   "responses": 152,
   "accuracy": 46
  },
  "label": "Κ11.8",
  "path": "questions/kahoot/kahoot-pointer-size.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-pointer-size.html",
  "statement": "Οι μεταβλητές `double *x;` και `char *c;` καταλαμβάνουν τον ίδιο χώρο στη μνήμη.\n\n- True\n- False\n\n## Συχνή παρανόηση\n\nΤο 49% απάντησε False, μπερδεύοντας το μέγεθος του δείκτη με το μέγεθος του τύπου στον οποίο δείχνει. Κάθε δείκτης κρατά μια διεύθυνση, άρα όλοι έχουν το ίδιο μέγεθος (8 bytes σε 64-bit συστήματα).",
  "hint": "Τι αποθηκεύει μια μεταβλητή δείκτη, και εξαρτάται το μέγεθος αυτού που αποθηκεύει από τον τύπο στον οποίο δείχνει;"
 },
 {
  "id": "kahoot-post-pre-increment",
  "kind": "kahoot",
  "title": "x++ και ++y",
  "source": {
   "title": "Kahoot «Τελεστές, Εντολές και Ροή Ελέγχου» (διάλεξη 6)",
   "years": [
    2025
   ]
  },
  "chapters": [
   5
  ],
  "topics": [
   "operators"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "42 43",
  "stats": {
   "responses": 245,
   "accuracy": 48
  },
  "label": "Κ5.3",
  "path": "questions/kahoot/kahoot-post-pre-increment.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-post-pre-increment.html",
  "statement": "Τι θα τυπώσει το πρόγραμμα;\n\n```c\nint x = 42, y = 42;\nprintf(\"%d %d\", x++, ++y);\n```\n\n- 42 42\n- 43 42\n- 42 43\n- 43 43",
  "hint": "Και οι δύο τελεστές αυξάνουν τη μεταβλητή κατά 1· η διαφορά τους είναι ποια τιμή έχει η ίδια η παράσταση, πριν ή μετά την αύξηση."
 },
 {
  "id": "kahoot-preprocessor-output",
  "kind": "kahoot",
  "title": "Η έξοδος του προεπεξεργαστή",
  "source": {
   "title": "Kahoot «Δυαδική Αναζήτηση, Ταξινόμηση, Πολυπλοκότητα και άλλα» και «Πολυπλοκότητα και άλλα» (διάλεξη 15)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   15
  ],
  "topics": [
   "preprocessor",
   "compilation"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "Πηγαίου Κώδικα",
  "stats": {
   "responses": 154,
   "accuracy": 38
  },
  "label": "Κ15.7",
  "path": "questions/kahoot/kahoot-preprocessor-output.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-preprocessor-output.html",
  "statement": "Η έξοδος του προεπεξεργαστή είναι ένα αρχείο:\n\n- Δυαδικού κώδικα\n- Κώδικα assembly\n- Πηγαίου Κώδικα\n- Εξαρτάται\n\n## Συχνή παρανόηση\n\nΤο 30% απάντησε «Εξαρτάται», χωρίς να έχει ξεκαθαρίσει τη θέση του προεπεξεργαστή στη σειρά προεπεξεργασία → μεταγλώττιση → συμβολομετάφραση → σύνδεση: ο προεπεξεργαστής κάνει πάντα μόνο αντικαταστάσεις κειμένου.",
  "hint": "Σκεφτείτε τι κάνουν οι οδηγίες `#include` και `#define`: αντικαθιστούν κείμενο. Τι παραλαμβάνει στη συνέχεια ο μεταγλωττιστής; Δοκιμάστε `gcc -E`."
 },
 {
  "id": "kahoot-printf-carriage-return",
  "kind": "kahoot",
  "title": "Η ακολουθία `\\r`",
  "source": {
   "title": "Kahoot «Τύπωμα και Συναρτήσεις» (διάλεξη 3)",
   "years": [
    2025
   ]
  },
  "chapters": [
   3
  ],
  "topics": [
   "input-output"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "world",
  "stats": {
   "responses": 190,
   "accuracy": 48
  },
  "label": "Κ3.4",
  "path": "questions/kahoot/kahoot-printf-carriage-return.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-printf-carriage-return.html",
  "statement": "Τι θα δω στην οθόνη αν τρέξω `printf(\"hello\\rworld\");`\n\n- hello\n- world\n- hello world\n- hellorworld",
  "hint": "Το `\\r` (carriage return) δεν αλλάζει γραμμή· σκεφτείτε πού μετακινεί τον κέρσορα και τι γίνεται με όσα γράφονται μετά."
 },
 {
  "id": "kahoot-printf-char-42",
  "kind": "kahoot",
  "title": "printf με %c και 42",
  "source": {
   "title": "Kahoot «Τύπωμα και Συναρτήσεις» (διάλεξη 3)",
   "years": [
    2025
   ]
  },
  "chapters": [
   3
  ],
  "topics": [
   "input-output",
   "types"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "*",
  "stats": {
   "responses": 190,
   "accuracy": 48
  },
  "label": "Κ3.5",
  "path": "questions/kahoot/kahoot-printf-char-42.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-printf-char-42.html",
  "statement": "Η εκτέλεση της `printf(\"%c\", 42);` θα τυπώσει:\n\n- %c\n- *\n- 42\n- 0x42\n\n## Συχνή παρανόηση\n\nΤο 24% επέλεξε `42`, σαν το `%c` να τυπώνει τον αριθμό· το `%c` τυπώνει τον χαρακτήρα με αυτόν τον κωδικό ASCII.",
  "hint": "Το `%c` ερμηνεύει τον ακέραιο ως κωδικό χαρακτήρα· ψάξτε ποιος χαρακτήρας έχει κωδικό ASCII 42 (`man ascii`)."
 },
 {
  "id": "kahoot-printf-escapes-backslash-quote",
  "kind": "kahoot",
  "title": "Ακολουθίες διαφυγής για `\\\\` και `\"`",
  "source": {
   "title": "Kahoot «Τύπωμα και Συναρτήσεις» (διάλεξη 3)",
   "years": [
    2025
   ]
  },
  "chapters": [
   3
  ],
  "topics": [
   "input-output",
   "strings"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "printf(\"I'm \\\\\\\\ \\\"back\\\"\");",
  "stats": {
   "responses": 190,
   "accuracy": 43
  },
  "label": "Κ3.6",
  "path": "questions/kahoot/kahoot-printf-escapes-backslash-quote.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-printf-escapes-backslash-quote.html",
  "statement": "Πώς τυπώνουμε την ακολουθία: `I'm \\\\ \"back\"`\n\n- `printf(\"I'm \\\\\\\\ \\\"back\\\"\");`\n- `printf(\"I\\'m \\\\ \\\"back\\\"\");`\n- `printf(\"I'm \\\\ \"back\"\");`\n- `printf(\"I am \\n %dback%d\");`",
  "hint": "Μέσα σε ένα αλφαριθμητικό, κάθε `\\` που θέλουμε να τυπωθεί και κάθε `\"` πρέπει να γραφτεί με ακολουθία διαφυγής. Μετρήστε πόσα `\\` θέλουμε στην έξοδο."
 },
 {
  "id": "kahoot-printf-format-order",
  "kind": "kahoot",
  "title": "Προσδιοριστικά %d με σειρά",
  "source": {
   "title": "Kahoot «Τύπωμα και Συναρτήσεις» (διάλεξη 3)",
   "years": [
    2025
   ]
  },
  "chapters": [
   3
  ],
  "topics": [
   "input-output"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "England-Greece 1-2",
  "stats": {
   "responses": 190,
   "accuracy": 87
  },
  "label": "Κ3.1",
  "path": "questions/kahoot/kahoot-printf-format-order.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-printf-format-order.html",
  "statement": "Τι θα τυπώσει η `printf(\"England-Greece %d-%d\", 1, 2);`\n\n- England-Greece 1-2\n- England-Greece -1\n- England-Greece %d-%d\n- England-Greece 2-1",
  "hint": "Κάθε `%d` αντικαθίσταται με το επόμενο όρισμα, με τη σειρά που δίνονται."
 },
 {
  "id": "kahoot-printf-newline",
  "kind": "kahoot",
  "title": "Εκτύπωση με νέα γραμμή",
  "source": {
   "title": "Kahoot «Καλημέρα Κόσμε - lec00!», «Καλημέρα Κόσμε!» (διάλεξη 0)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   0,
   2
  ],
  "topics": [
   "input-output"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "printf(\"Michael Jordan\\n\");",
  "stats": {
   "responses": 330,
   "accuracy": 86
  },
  "label": "Κ0.2",
  "path": "questions/kahoot/kahoot-printf-newline.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-printf-newline.html",
  "statement": "Παραλλαγή θέματος εξέτασης: ποια από τις παρακάτω γραμμές τυπώνει `Michael Jordan` ακολουθούμενο από νέα γραμμή;\n\n- `print \"Michael Jordan\";`\n- `printf(\"Michael Jordan\\n\");`\n- `printf(\"Michael Jordan\");`\n- `print(Lebron James);`",
  "hint": "Ελέγξτε το όνομα της συνάρτησης, τις παρενθέσεις και τα εισαγωγικά, και ποια ακολουθία διαφυγής αλλάζει γραμμή."
 },
 {
  "id": "kahoot-printf-prints",
  "kind": "kahoot",
  "title": "Τι κάνει η printf",
  "source": {
   "title": "Kahoot «Καλημέρα Κόσμε - lec00!», «Καλημέρα Κόσμε!» (διάλεξη 0)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   0
  ],
  "topics": [
   "input-output"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "Τυπώνει",
  "stats": {
   "responses": 330,
   "accuracy": 94
  },
  "label": "Κ0.1",
  "path": "questions/kahoot/kahoot-printf-prints.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-printf-prints.html",
  "statement": "Τι κάνει η συνάρτηση `printf`;\n\n- Τυπώνει\n- Διαβάζει\n- Δεν θυμάμαι :)",
  "hint": "Θυμηθείτε το πρώτο πρόγραμμα του μαθήματος, το Hello World."
 },
 {
  "id": "kahoot-ptr-index-offset",
  "kind": "kahoot",
  "title": "Δείκτης στη μέση πίνακα",
  "source": {
   "title": "Kahoot «Δείκτες και Αναδρομή» (διάλεξη 11) και «Δείκτες Παντού!» (διάλεξη 12)",
   "years": [
    2025
   ]
  },
  "chapters": [
   11,
   10
  ],
  "topics": [
   "pointers",
   "pointer-arithmetic",
   "arrays"
  ],
  "difficulty": 3,
  "type": "short-answer",
  "answer": "30",
  "stats": {
   "responses": 232,
   "accuracy": 12
  },
  "label": "Κ11.14",
  "path": "questions/kahoot/kahoot-ptr-index-offset.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-ptr-index-offset.html",
  "statement": "Τι θα τυπώσει ο παρακάτω κώδικας;\n\n```c\nint a[] = {10, 20, 30, 40};\nint *ptr = &a[1];\nprintf(\"%d\", ptr[1]);\n```\n\nΓράψτε την απάντηση.",
  "hint": "Το `ptr[n]` σημαίνει `*(ptr + n)`, και μετράει από εκεί που δείχνει ο `ptr`, όχι από την αρχή του πίνακα."
 },
 {
  "id": "kahoot-ptr-offset-equals-index",
  "kind": "kahoot",
  "title": "*(ptr + 4) και ptr[4]",
  "source": {
   "title": "Kahoot «Δείκτες και Αναδρομή» (διάλεξη 11)",
   "years": [
    2025
   ]
  },
  "chapters": [
   11
  ],
  "topics": [
   "pointer-arithmetic",
   "arrays"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "True",
  "stats": {
   "responses": 152,
   "accuracy": 67
  },
  "label": "Κ11.3",
  "path": "questions/kahoot/kahoot-ptr-offset-equals-index.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-ptr-offset-equals-index.html",
  "statement": "Η έκφραση `*(ptr + 4)` είναι ισοδύναμη με την έκφραση `ptr[4]`.\n\n- True\n- False\n\n## Συχνή παρανόηση\n\nΤο 26% απάντησε False, θεωρώντας ότι οι αγκύλες είναι κάτι διαφορετικό από την αριθμητική δεικτών. Στην C το `ptr[n]` ορίζεται ακριβώς ως `*(ptr + n)`.",
  "hint": "Θυμηθείτε πώς ορίζει η C τον τελεστή `[]` με βάση την αριθμητική δεικτών."
 },
 {
  "id": "kahoot-qsort-compare-ascending",
  "kind": "kahoot",
  "title": "Συνάρτηση σύγκρισης για αύξουσα ταξινόμηση",
  "source": {
   "title": "Kahoot «Ταξινόμηση και Δομές»",
   "years": [
    2025
   ]
  },
  "chapters": [
   18,
   17,
   19
  ],
  "topics": [
   "sorting",
   "structs",
   "function-pointers"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "int comp(... s1, ... s2) { return s1.grade - s2.grade; }",
  "stats": {
   "responses": 127,
   "accuracy": 12
  },
  "label": "Κ18.5",
  "path": "questions/kahoot/kahoot-qsort-compare-ascending.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-qsort-compare-ascending.html",
  "statement": "Θέλω να ταξινομήσω σε αύξουσα σειρά βαθμολογίας τον πίνακα `struct student[1024]`. Χρησιμοποιώ τη συνάρτηση σύγκρισης:\n\n- `int comp(... s1, ... s2) { return s1.grade - s2.grade; }`\n- `int comp(... s1, ... s2) { return s2.grade - s1.grade; }`\n- `int comp(... s1, ... s2) { return s1.grade == s2.grade; }`\n- `int comp(... s1, ... s2) { return s1.grade ^ s2.grade; }`\n\n## Συχνή παρανόηση\n\nΤο 43% επέλεξε `s2.grade - s1.grade`, αντιστρέφοντας τη σύμβαση: αρνητική τιμή σημαίνει ότι το `s1` μπαίνει πρώτο, οπότε η αφαίρεση `s2 - s1` δίνει φθίνουσα σειρά. Οι επιλογές με `==` και `^` (20% η καθεμία) δεν δίνουν καν πρόσημο που να λέει ποιο στοιχείο προηγείται.",
  "hint": "Η συνάρτηση σύγκρισης της `qsort` επιστρέφει αρνητικό, μηδέν ή θετικό· σκεφτείτε ποιο πρόσημο σημαίνει «το πρώτο όρισμα πάει πριν από το δεύτερο» και δοκιμάστε με δύο βαθμούς, π.χ. 5 και 8."
 },
 {
  "id": "kahoot-quicksort-average",
  "kind": "kahoot",
  "title": "Μέση πολυπλοκότητα της quicksort",
  "source": {
   "title": "Kahoot «Δυαδική Αναζήτηση και Ταξινόμηση» (διάλεξη 17)",
   "years": [
    2025
   ]
  },
  "chapters": [
   17,
   18
  ],
  "topics": [
   "sorting",
   "complexity"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "O(n log n)",
  "stats": {
   "responses": 71,
   "accuracy": 66
  },
  "label": "Κ17.5",
  "path": "questions/kahoot/kahoot-quicksort-average.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-quicksort-average.html",
  "statement": "Η χρονική πολυπλοκότητα στη μέση περίπτωση (average case) της quicksort είναι:\n\n- O(n²)\n- O(n log n)\n- O(n)\n- O(1)",
  "hint": "Σκεφτείτε πόσα επίπεδα διαμέρισης έχει η quicksort όταν ο pivot χωρίζει τον πίνακα περίπου στη μέση, και πόση δουλειά γίνεται σε κάθε επίπεδο."
 },
 {
  "id": "kahoot-readme-markdown",
  "kind": "kahoot",
  "title": "Η γλώσσα του README.md",
  "source": {
   "title": "Kahoot «Επίλυση Προβλημάτων» (διάλεξη 7)",
   "years": [
    2025
   ]
  },
  "chapters": [
   7
  ],
  "topics": [
   "good-practice"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "Markdown",
  "stats": {
   "responses": 192,
   "accuracy": 84
  },
  "label": "Κ7.2",
  "path": "questions/kahoot/kahoot-readme-markdown.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-readme-markdown.html",
  "statement": "Η γλώσσα στην οποία γράφουμε το `README.md` μας λέγεται:\n\n- Parkdown\n- Markdown\n- Smackdown\n- Downtown",
  "hint": "Η κατάληξη `.md` του αρχείου είναι η συντομογραφία της."
 },
 {
  "id": "kahoot-recursion-terminates",
  "kind": "kahoot",
  "title": "Τερματισμός αναδρομής",
  "source": {
   "title": "Kahoot «Δείκτες και Αναδρομή» (διάλεξη 11) και «Δείκτες Παντού!» (διάλεξη 12)",
   "years": [
    2025
   ]
  },
  "chapters": [
   11,
   13
  ],
  "topics": [
   "recursion"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "True",
  "stats": {
   "responses": 232,
   "accuracy": 87
  },
  "label": "Κ11.1",
  "path": "questions/kahoot/kahoot-recursion-terminates.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-recursion-terminates.html",
  "statement": "Η αναδρομή πρέπει να τερματίζει.\n\n- True\n- False",
  "hint": "Τι γίνεται στη στοίβα σε κάθε νέα αναδρομική κλήση;"
 },
 {
  "id": "kahoot-scanf-int-syntax",
  "kind": "kahoot",
  "title": "Διάβασμα ακεραίου με scanf",
  "source": {
   "title": "Kahoot «Δεδομένα Εισόδου» (διάλεξη 9)",
   "years": [
    2025
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "scanf(\"%d\", &num)",
  "stats": {
   "responses": 244,
   "accuracy": 53
  },
  "label": "Κ9.6",
  "path": "questions/kahoot/kahoot-scanf-int-syntax.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-scanf-int-syntax.html",
  "statement": "Πώς διαβάζω έναν ακέραιο με την `scanf`;\n\n- `scanf(\"&d\", %num)`\n- `scanf(\"d%\", &num)`\n- `scanf(\"%d\", num);`\n- `scanf(\"%d\", &num)`",
  "hint": "Το προσδιοριστικό μορφοποίησης γράφεται όπως στην `printf`, και η `scanf` χρειάζεται να ξέρει πού βρίσκεται η μεταβλητή στη μνήμη για να γράψει σε αυτήν."
 },
 {
  "id": "kahoot-scanf-return-partial",
  "kind": "kahoot",
  "title": "Τιμή επιστροφής της scanf με λάθος είσοδο",
  "source": {
   "title": "Kahoot «Δεδομένα Εισόδου» (διάλεξη 9)",
   "years": [
    2025
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output",
   "input-validation"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "1",
  "stats": {
   "responses": 244,
   "accuracy": 11
  },
  "label": "Κ9.9",
  "path": "questions/kahoot/kahoot-scanf-return-partial.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-scanf-return-partial.html",
  "statement": "Έδωσα την ακολουθία `42 hello 43` στο πρόγραμμά μου:\n\n```c\nscanf(\"%d%d\", &n1, &n2);\n```\n\nΠοια η τιμή επιστροφής της `scanf`;\n\n- 42 42\n- 42 43\n- 1\n- EOF\n\n## Συχνή παρανόηση\n\nΤο 42% επέλεξε `42 43`, μπερδεύοντας την τιμή επιστροφής της `scanf` με τις τιμές που αποθηκεύει στις μεταβλητές, και ξεχνώντας ότι σταματά στο `hello`.",
  "hint": "Η `scanf` δεν επιστρέφει τις τιμές που διάβασε αλλά πόσες μετατροπές πέτυχαν. Σκεφτείτε πού σταματά όταν συναντήσει κάτι που δεν είναι ακέραιος."
 },
 {
  "id": "kahoot-seat-search-grid",
  "kind": "kahoot",
  "title": "Γραμμική αναζήτηση σε αμφιθέατρο n × n",
  "source": {
   "title": "Kahoot «Δυαδική Αναζήτηση, Ταξινόμηση, Πολυπλοκότητα και άλλα» και «Πολυπλοκότητα και άλλα» (διάλεξη 15)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   15
  ],
  "topics": [
   "complexity",
   "searching"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "O(n²)",
  "stats": {
   "responses": 154,
   "accuracy": 75
  },
  "label": "Κ15.1",
  "path": "questions/kahoot/kahoot-seat-search-grid.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-seat-search-grid.html",
  "statement": "Ψάχνω έναν γνωστό μου σε αμφιθέατρο διαστάσεων n × n, κοιτώντας μία-μία τις θέσεις. Ο αλγόριθμός μου είναι σε χρόνο:\n\n- O(n)\n- O(f(x))\n- O(n²)\n- O(1)",
  "hint": "Πόσες θέσεις έχει συνολικά το αμφιθέατρο, και πόσες θα κοιτάξετε στη χειρότερη περίπτωση;"
 },
 {
  "id": "kahoot-self-referential-struct",
  "kind": "kahoot",
  "title": "Αυτοαναφορική δομή",
  "source": {
   "title": "Kahoot «Προχωρημένες Δομές» (διάλεξη 20), «Προχωρημένες Δομές #2»",
   "years": [
    2025
   ]
  },
  "chapters": [
   20
  ],
  "topics": [
   "structs",
   "pointers"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "περιέχει ένα πεδίο τύπου δείκτη που δείχνει σε δομή ίδιου τύπου",
  "stats": {
   "responses": 164,
   "accuracy": 56
  },
  "label": "Κ20.4",
  "path": "questions/kahoot/kahoot-self-referential-struct.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-self-referential-struct.html",
  "statement": "Μια αυτοαναφορική δομή:\n\n- περιέχει τον εαυτό της\n- είναι ένα πεδίο τύπου δείκτη\n- περιέχει ένα πεδίο τύπου δείκτη που δείχνει σε δομή ίδιου τύπου\n- περιέχει αυτοαναφορικούς ακεραίους\n\n## Συχνή παρανόηση\n\nΤο 22% επέλεξε «περιέχει τον εαυτό της», κάτι αδύνατο: μια δομή που περιέχει αντίγραφο του εαυτού της θα είχε άπειρο μέγεθος.",
  "hint": "Σκεφτείτε πόσα bytes θα χρειαζόταν μια δομή που περιέχει ολόκληρη μια δομή του ίδιου τύπου, και τι μπορεί να περιέχει αντί γι' αυτό."
 },
 {
  "id": "kahoot-shift-left",
  "kind": "kahoot",
  "title": "3 << 2",
  "source": {
   "title": "Kahoot «Git και Τελεστές» (διάλεξη 4)",
   "years": [
    2025
   ]
  },
  "chapters": [
   4
  ],
  "topics": [
   "bitwise"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "12",
  "stats": {
   "responses": 318,
   "accuracy": 55
  },
  "label": "Κ4.4",
  "path": "questions/kahoot/kahoot-shift-left.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-shift-left.html",
  "statement": "Ποια η τιμή της παράστασης `3 << 2`;\n\n- `3`\n- `6`\n- `12`\n- `42`",
  "hint": "Γράψτε το 3 στο δυαδικό και μετακινήστε όλα τα bits δύο θέσεις αριστερά· κάθε μετατόπιση κατά μία θέση αντιστοιχεί σε έναν πολλαπλασιασμό."
 },
 {
  "id": "kahoot-signed-char-ff",
  "kind": "kahoot",
  "title": "Το 0xFF σε signed char",
  "source": {
   "title": "Kahoot «Μεταβλητές και Μνήμη», «Μεταβλητές και Συναρτήσεις» (διάλεξη 2)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "integer-representation",
   "types"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "-1",
  "stats": {
   "responses": 301,
   "accuracy": 33
  },
  "label": "Κ2.15",
  "path": "questions/kahoot/kahoot-signed-char-ff.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-signed-char-ff.html",
  "statement": "Για ένα `signed char` που έχει τιμή `0xFF` (συμπλήρωμα του δύο), ποια είναι η δεκαδική τιμή του;\n\n- 1\n- -1\n- 256\n- 0\n\n## Συχνή παρανόηση\n\nΤο 41% απάντησε 256, που δεν χωράει καν σε 8 bits (το `0xFF` ως unsigned είναι 255)· σε `signed char` με συμπλήρωμα ως προς 2 όλοι οι άσοι σημαίνουν αρνητικό αριθμό.",
  "hint": "Στο συμπλήρωμα ως προς 2 το πιο σημαντικό bit δείχνει το πρόσημο. Για να βρείτε το μέτρο ενός αρνητικού, κάντε flip όλα τα bits και προσθέστε 1."
 },
 {
  "id": "kahoot-sizeof-2d-double",
  "kind": "kahoot",
  "title": "sizeof δισδιάστατου πίνακα",
  "source": {
   "title": "Kahoot «Πίνακες και Δείκτες» (διάλεξη 12)",
   "years": [
    2025
   ]
  },
  "chapters": [
   12
  ],
  "topics": [
   "multidim-arrays",
   "types"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "800",
  "stats": {
   "responses": 141,
   "accuracy": 68
  },
  "label": "Κ12.4",
  "path": "questions/kahoot/kahoot-sizeof-2d-double.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-sizeof-2d-double.html",
  "statement": "Έστω `sizeof(double) == 8` και πίνακας `double coeffs[10][10]`. Πόσο είναι το `sizeof(coeffs)`;\n\n- `800`\n- `100`\n- `160`\n- Εξαρτάται",
  "hint": "Πόσα στοιχεία έχει συνολικά ο πίνακας, και πόσα bytes πιάνει το καθένα;"
 },
 {
  "id": "kahoot-sizeof-row",
  "kind": "kahoot",
  "title": "sizeof μιας γραμμής",
  "source": {
   "title": "Kahoot «Πίνακες και Δείκτες» (διάλεξη 12)",
   "years": [
    2025
   ]
  },
  "chapters": [
   12
  ],
  "topics": [
   "multidim-arrays",
   "types"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "10",
  "stats": {
   "responses": 141,
   "accuracy": 42
  },
  "label": "Κ12.7",
  "path": "questions/kahoot/kahoot-sizeof-row.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-sizeof-row.html",
  "statement": "Έστω `sizeof(char) == 1` και πίνακας `char map[10][10]`. Πόσο είναι το `sizeof(map[5])`;\n\n- `1`\n- `10`\n- `100`\n- Εξαρτάται\n\n## Συχνή παρανόηση\n\nΤο 26% επέλεξε `1`, θεωρώντας ότι το `map[5]` είναι ένας χαρακτήρας. Στην πραγματικότητα το `map[5]` είναι ολόκληρη η 6η γραμμή, ένας πίνακας 10 `char`.",
  "hint": "Με έναν μόνο δείκτη σε δισδιάστατο πίνακα, τι παίρνουμε: ένα στοιχείο ή μια ολόκληρη γραμμή;"
 },
 {
  "id": "kahoot-sort-million-ints",
  "kind": "kahoot",
  "title": "Ταξινόμηση ενός εκατομμυρίου ακεραίων",
  "source": {
   "title": "Kahoot «Δυαδική Αναζήτηση και Ταξινόμηση» (διάλεξη 17) και «Δυαδική Αναζήτηση, Ταξινόμηση, Πολυπλοκότητα και άλλα»",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   17,
   18
  ],
  "topics": [
   "sorting",
   "complexity"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "mergesort",
  "stats": {
   "responses": 101,
   "accuracy": 68
  },
  "label": "Κ17.4",
  "path": "questions/kahoot/kahoot-sort-million-ints.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-sort-million-ints.html",
  "statement": "Ποιος είναι χρονικά ο πιο αποδοτικός τρόπος να ταξινομήσεις $10^6$ ακεραίους 32-bit;\n\n- bubblesort\n- insertion sort\n- mergesort\n- selection sort",
  "hint": "Συγκρίνετε την πολυπλοκότητα χειρότερης περίπτωσης των τεσσάρων αλγορίθμων και υπολογίστε χονδρικά πόσες πράξεις σημαίνει η καθεμία για $n = 10^6$."
 },
 {
  "id": "kahoot-sort-worst-case",
  "kind": "kahoot",
  "title": "Η πιο γρήγορη ταξινόμηση στη χειρότερη περίπτωση",
  "source": {
   "title": "Kahoot «Δυαδική Αναζήτηση και Ταξινόμηση» (διάλεξη 17)",
   "years": [
    2025
   ]
  },
  "chapters": [
   17,
   18
  ],
  "topics": [
   "sorting",
   "complexity"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "Καμία, όλες είναι O(n²)",
  "stats": {
   "responses": 71,
   "accuracy": 28
  },
  "label": "Κ17.8",
  "path": "questions/kahoot/kahoot-sort-worst-case.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-sort-worst-case.html",
  "statement": "Ποια μέθοδος ταξινόμησης είναι πιο γρήγορη στη χειρότερη περίπτωση;\n\n- insertion sort\n- selection sort\n- quicksort\n- bubblesort\n- Καμία, όλες είναι O(n²)\n\n## Συχνή παρανόηση\n\nΤο 35% επέλεξε την quicksort, που είναι O(n log n) στη μέση περίπτωση αλλά O(n²) στη χειρότερη (κακή επιλογή pivot). Ένα 27% επέλεξε την bubblesort, ίσως επειδή τελειώνει γρήγορα σε ήδη ταξινομημένο πίνακα, που όμως είναι η καλύτερη και όχι η χειρότερη περίπτωση.",
  "hint": "Για κάθε αλγόριθμο, σκεφτείτε ποια είσοδος είναι η χειρότερη δυνατή, και για την quicksort ειδικά, τι γίνεται όταν ο pivot είναι πάντα το μικρότερο ή το μεγαλύτερο στοιχείο."
 },
 {
  "id": "kahoot-square-double-return",
  "kind": "kahoot",
  "title": "Τιμή επιστροφής double",
  "source": {
   "title": "Kahoot «Τύπωμα και Συναρτήσεις» (διάλεξη 3)",
   "years": [
    2025
   ]
  },
  "chapters": [
   3
  ],
  "topics": [
   "functions",
   "types"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "256.0",
  "stats": {
   "responses": 190,
   "accuracy": 58
  },
  "label": "Κ3.2",
  "path": "questions/kahoot/kahoot-square-double-return.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-square-double-return.html",
  "statement": "Ποια η τιμή που θα επιστρέψει η `square(16.0)`, εφόσον:\n\n```c\ndouble square(double x) { return x * x; }\n```\n\n- 0\n- 256\n- 256.0\n- 42",
  "hint": "Ο τύπος της τιμής που επιστρέφει μια συνάρτηση ορίζεται στην αρχή του ορισμού της."
 },
 {
  "id": "kahoot-stack-lifo",
  "kind": "kahoot",
  "title": "Αφαίρεση από στοίβα",
  "source": {
   "title": "Kahoot «Δείκτες Παντού!» (διάλεξη 12) και «Μνήμη» (διάλεξη 13)",
   "years": [
    2025
   ]
  },
  "chapters": [
   13
  ],
  "topics": [
   "memory-model"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "πάντα το τελευταίο που βάλαμε στην στοίβα",
  "stats": {
   "responses": 215,
   "accuracy": 80
  },
  "label": "Κ13.3",
  "path": "questions/kahoot/kahoot-stack-lifo.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-stack-lifo.html",
  "statement": "Όταν αφαιρούμε ένα στοιχείο από μια στοίβα με πολλά στοιχεία, αυτό είναι:\n\n- πάντα το τελευταίο που βάλαμε στην στοίβα\n- πάντα το πρώτο που βάλαμε στην στοίβα\n- οποιοδήποτε στοιχείο της στοίβας\n- το 42ο στην σειρά",
  "hint": "Σκεφτείτε μια στοίβα από πιάτα, ή τη σειρά με την οποία επιστρέφουν οι κλήσεις συναρτήσεων."
 },
 {
  "id": "kahoot-stack-overflow-depth",
  "kind": "kahoot",
  "title": "Βάθος αναδρομής μέχρι να γεμίσει η στοίβα",
  "source": {
   "title": "Kahoot «Μνήμη» (διάλεξη 13)",
   "years": [
    2025
   ]
  },
  "chapters": [
   13
  ],
  "topics": [
   "recursion",
   "memory-model",
   "shell"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "~8000",
  "stats": {
   "responses": 135,
   "accuracy": 20
  },
  "label": "Κ13.11",
  "path": "questions/kahoot/kahoot-stack-overflow-depth.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-stack-overflow-depth.html",
  "statement": "Έστω ότι `ulimit -s` δίνει 8192 και το activation record της `foo` είναι 1024 bytes. Πόσες αναδρομικές κλήσεις μέχρι να «σκάσει» το πρόγραμμα;\n\n- ~8\n- 42\n- ~400\n- ~8000\n\n## Συχνή παρανόηση\n\nΤο 48% επέλεξε `~8`, θεωρώντας ότι το 8192 είναι bytes. Το `ulimit -s` μετράει σε KB, άρα η στοίβα είναι 8 MB.",
  "hint": "Ελέγξτε σε ποια μονάδα μετράει το `ulimit -s` το μέγεθος της στοίβας."
 },
 {
  "id": "kahoot-static-vs-dynamic-arrays",
  "kind": "kahoot",
  "title": "Στατικοί και δυναμικοί πίνακες",
  "source": {
   "title": "Kahoot «Δείκτες Παντού!» (διάλεξη 12) και «Πίνακες και Δείκτες» (διάλεξη 12)",
   "years": [
    2025
   ]
  },
  "chapters": [
   12,
   13
  ],
  "topics": [
   "arrays",
   "dynamic-memory",
   "memory-model"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "False",
  "stats": {
   "responses": 221,
   "accuracy": 92
  },
  "label": "Κ12.2",
  "path": "questions/kahoot/kahoot-static-vs-dynamic-arrays.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-static-vs-dynamic-arrays.html",
  "statement": "Δεν υπάρχει διαφορά ανάμεσα σε στατικούς και δυναμικούς πίνακες.\n\n- True\n- False",
  "hint": "Σκεφτείτε πού βρίσκεται η μνήμη του καθενός, πότε ορίζεται το μέγεθός του και ποιος την αποδεσμεύει."
 },
 {
  "id": "kahoot-stderr-fd",
  "kind": "kahoot",
  "title": "Ο file descriptor του stderr",
  "source": {
   "title": "Kahoot «Δομές + Αρχεία», «Δυαδική Αναζήτηση και Ταξινόμηση» (διάλεξη 17)",
   "years": [
    2025
   ]
  },
  "chapters": [
   18
  ],
  "topics": [
   "files",
   "redirection",
   "input-output"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "2",
  "stats": {
   "responses": 95,
   "accuracy": 51
  },
  "label": "Κ18.3",
  "path": "questions/kahoot/kahoot-stderr-fd.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-stderr-fd.html",
  "statement": "Το `stderr` έχει συνήθως file descriptor με αριθμό:\n\n- 0\n- 1\n- 2\n- 3\n\n## Συχνή παρανόηση\n\nΤο 29% επέλεξε `1`, που είναι ο αριθμός του `stdout`· τα τρία πρότυπα ρεύματα έχουν τους πρώτους αριθμούς με τη σειρά `stdin`, `stdout`, `stderr`.",
  "hint": "Θυμηθείτε τη σειρά των τριών ρευμάτων που ανοίγουν αυτόματα και ότι η αρίθμηση ξεκινάει από το 0 (σκεφτείτε και το `2>` του shell)."
 },
 {
  "id": "kahoot-stdin-vs-files",
  "kind": "kahoot",
  "title": "stdin και αρχεία",
  "source": {
   "title": "Kahoot «Δομές + Αρχεία», «Δυαδική Αναζήτηση και Ταξινόμηση» (διάλεξη 17)",
   "years": [
    2025
   ]
  },
  "chapters": [
   18
  ],
  "topics": [
   "files",
   "input-output",
   "redirection"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "False",
  "stats": {
   "responses": 95,
   "accuracy": 84
  },
  "label": "Κ18.1",
  "path": "questions/kahoot/kahoot-stdin-vs-files.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-stdin-vs-files.html",
  "statement": "Η πρότυπη είσοδος `stdin` και τα ανοιγμένα αρχεία στην C δεν έχουν καμία σχέση.\n\n- True\n- False",
  "hint": "Κοιτάξτε ποιος είναι ο τύπος του `stdin` και αν μπορείτε να το δώσετε σε συναρτήσεις όπως η `fscanf`."
 },
 {
  "id": "kahoot-strcat-self-overflow",
  "kind": "kahoot",
  "title": "Η strcat με τον εαυτό της",
  "source": {
   "title": "Kahoot «Δυαδική Αναζήτηση, Ταξινόμηση, Πολυπλοκότητα και άλλα» και «Εμβέλεια, Μνήμη και Συμβολοσειρές» (διάλεξη 14)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   14
  ],
  "topics": [
   "strings",
   "undefined-behavior",
   "arrays"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "Πιθανόν να κρασάρει",
  "stats": {
   "responses": 127,
   "accuracy": 24
  },
  "label": "Κ14.7",
  "path": "questions/kahoot/kahoot-strcat-self-overflow.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-strcat-self-overflow.html",
  "statement": "Τι θα τυπώσει ο παρακάτω κώδικας;\n\n```c\nchar fruit[10];\nstrcpy(fruit, \"banana\");\nstrcat(fruit, fruit);\nstrcat(fruit, fruit);\nprintf(\"%s\", fruit);\n```\n\n- banana\n- bananabanana\n- bananabananabananabanana\n- Πιθανόν να κρασάρει\n\n## Συχνή παρανόηση\n\nΤο 34% επέλεξε `bananabananabananabanana` και το 24% `bananabanana`, κοιτάζοντας μόνο τη λογική της συνένωσης: ο πίνακας έχει 10 bytes, οπότε ήδη η πρώτη `strcat` γράφει εκτός ορίων, και η επικάλυψη πηγής και προορισμού είναι από μόνη της απροσδιόριστη συμπεριφορά.",
  "hint": "Μετρήστε πόσα bytes χρειάζεται το αποτέλεσμα, μαζί με το `'\\0'`, και συγκρίνετε με το μέγεθος του `fruit`. Σκεφτείτε επίσης τι σημαίνει για την `strcat` να διαβάζει από τον ίδιο πίνακα στον οποίο γράφει."
 },
 {
  "id": "kahoot-strcat-sequence",
  "kind": "kahoot",
  "title": "Διαδοχικές strcat",
  "source": {
   "title": "Kahoot «Εμβέλεια, Μνήμη και Συμβολοσειρές» (διάλεξη 14)",
   "years": [
    2025
   ]
  },
  "chapters": [
   14
  ],
  "topics": [
   "strings"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "HiHow are you doing",
  "stats": {
   "responses": 97,
   "accuracy": 60
  },
  "label": "Κ14.3",
  "path": "questions/kahoot/kahoot-strcat-sequence.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-strcat-sequence.html",
  "statement": "Τι θα τυπώσει ο παρακάτω κώδικας;\n\n```c\nchar str[100];\nstrcpy(str, \"Hi\");\nstrcat(str, \"How\");\nstrcat(str, \" are you doing\");\nprintf(\"%s\", str);\n```\n\n- Hi\n- How are you doing\n- HiHow are you doing\n- Θα κρασάρει",
  "hint": "Θυμηθείτε ποια συνάρτηση αντικαθιστά το περιεχόμενο του προορισμού και ποια προσθέτει στο τέλος του, και προσέξτε πού υπάρχουν κενά."
 },
 {
  "id": "kahoot-strcmp-equal",
  "kind": "kahoot",
  "title": "Η τιμή της strcmp για ίσες συμβολοσειρές",
  "source": {
   "title": "Kahoot «Δυαδική Αναζήτηση, Ταξινόμηση, Πολυπλοκότητα και άλλα» και «Εμβέλεια, Μνήμη και Συμβολοσειρές» (διάλεξη 14)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   14
  ],
  "topics": [
   "strings"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "0",
  "stats": {
   "responses": 127,
   "accuracy": 48
  },
  "label": "Κ14.5",
  "path": "questions/kahoot/kahoot-strcmp-equal.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-strcmp-equal.html",
  "statement": "Ποια η τιμή της έκφρασης `strcmp(\"Hodor\", \"Hodor\")`;\n\n- 0\n- 1\n- 42\n- Hodor\n\n## Συχνή παρανόηση\n\nΤο 30% επέλεξε 1, διαβάζοντας την `strcmp` σαν έλεγχο ισότητας που επιστρέφει «αληθές» όταν οι συμβολοσειρές είναι ίδιες.",
  "hint": "Η `strcmp` δεν απαντά «ναι/όχι» αλλά συγκρίνει λεξικογραφικά: το πρόσημο του αποτελέσματος λέει ποια συμβολοσειρά προηγείται."
 },
 {
  "id": "kahoot-strcpy-literal-to-array",
  "kind": "kahoot",
  "title": "strcpy από literal σε πίνακα",
  "source": {
   "title": "Kahoot «Εμβέλεια, Μνήμη και Συμβολοσειρές» (διάλεξη 14)",
   "years": [
    2025
   ]
  },
  "chapters": [
   14
  ],
  "topics": [
   "strings",
   "pointers"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "World",
  "stats": {
   "responses": 97,
   "accuracy": 32
  },
  "label": "Κ14.6",
  "path": "questions/kahoot/kahoot-strcpy-literal-to-array.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-strcpy-literal-to-array.html",
  "statement": "Τι θα τυπώσει ο παρακάτω κώδικας;\n\n```c\nchar *s1 = \"World\", s2[] = \"Hello\";\nstrcpy(s2, s1);\nprintf(\"%s\\n\", s2);\n```\n\n- Hello\n- World\n- HelloWorld\n- Θα κρασάρει\n\n## Συχνή παρανόηση\n\nΤο 24% απάντησε ότι θα κρασάρει, μπερδεύοντας τους ρόλους: η `strcpy` γράφει στον πίνακα `s2`, που είναι εγγράψιμος και χωράει τα 6 bytes του `\"World\"`· το literal `s1` μόνο διαβάζεται.",
  "hint": "Ποιος από τους δύο είναι πίνακας που μπορούμε να γράψουμε και ποιος δείχνει σε string literal; Σε ποιον γράφει η `strcpy`, και χωράει εκεί το αποτέλεσμα;"
 },
 {
  "id": "kahoot-string-array-element",
  "kind": "kahoot",
  "title": "Χαρακτήρας από πίνακα συμβολοσειρών",
  "source": {
   "title": "Kahoot «Δείκτες Παντού!» (διάλεξη 12) και «Πίνακες και Δείκτες» (διάλεξη 12)",
   "years": [
    2025
   ]
  },
  "chapters": [
   12,
   14
  ],
  "topics": [
   "pointers",
   "strings",
   "multidim-arrays"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "'n'",
  "stats": {
   "responses": 221,
   "accuracy": 38
  },
  "label": "Κ12.8",
  "path": "questions/kahoot/kahoot-string-array-element.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-string-array-element.html",
  "statement": "Έστω ότι\n\n```c\nchar *strings[] = { \"Hello\", \"fine\", \"world\", NULL };\n```\n\nΤο στοιχείο `strings[1][2]` είναι:\n\n- `'e'`\n- `NULL`\n- `\"fine\"`\n- `'n'`\n\n## Συχνή παρανόηση\n\nΤο 23% επέλεξε `\"fine\"` και άλλο 22% `'e'`: οι πρώτοι σταμάτησαν στο `strings[1]` αγνοώντας τον δεύτερο δείκτη, οι δεύτεροι μέτρησαν τις θέσεις από το 1.",
  "hint": "Ο πρώτος δείκτης διαλέγει συμβολοσειρά και ο δεύτερος χαρακτήρα μέσα σε αυτή· και οι δύο μετράνε από το 0."
 },
 {
  "id": "kahoot-string-char-index",
  "kind": "kahoot",
  "title": "Χαρακτήρας σε συμβολοσειρά",
  "source": {
   "title": "Kahoot «Πίνακες» (διάλεξη 10)",
   "years": [
    2025
   ]
  },
  "chapters": [
   10
  ],
  "topics": [
   "arrays",
   "strings"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "W",
  "stats": {
   "responses": 249,
   "accuracy": 27
  },
  "label": "Κ10.9",
  "path": "questions/kahoot/kahoot-string-char-index.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-string-char-index.html",
  "statement": "Τι θα τυπώσει ο παρακάτω κώδικας;\n\n```c\nchar hello[] = \"Hello World\";\nprintf(\"%c\", hello[6]);\n```\n\n- `H`\n- `W`\n- `o`\n- (κενό)\n\n## Συχνή παρανόηση\n\nΤο 47% επέλεξε «(κενό)», μετρώντας τις θέσεις από το 1. Το κενό είναι το `hello[5]`, γιατί η αρίθμηση στους πίνακες ξεκινά από το 0.",
  "hint": "Μετρήστε τους χαρακτήρες ξεκινώντας από το 0, μετρώντας και το κενό."
 },
 {
  "id": "kahoot-struct-assignment",
  "kind": "kahoot",
  "title": "Ανάθεση δομών",
  "source": {
   "title": "Kahoot «Δομές + Αρχεία», «Ταξινόμηση και Δομές»",
   "years": [
    2025
   ]
  },
  "chapters": [
   19
  ],
  "topics": [
   "structs",
   "operators"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "1",
  "stats": {
   "responses": 151,
   "accuracy": 49
  },
  "label": "Κ19.7",
  "path": "questions/kahoot/kahoot-struct-assignment.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-struct-assignment.html",
  "statement": "Έστω `struct {int x;} cafe = {1}, bar = {2}; bar = cafe;`. Η παράσταση `bar.x` αποτιμάται σε:\n\n- 1\n- 2\n- Δεν αποτιμάται\n- 42\n\n## Συχνή παρανόηση\n\nΤο 28% επέλεξε `2`, σαν η ανάθεση `bar = cafe` να μην άλλαζε τα πεδία της `bar`· στην πραγματικότητα η ανάθεση δομών αντιγράφει όλα τα πεδία.",
  "hint": "Αναρωτηθείτε αν ο τελεστής `=` επιτρέπεται ανάμεσα σε δύο δομές του ίδιου τύπου και τι αντιγράφει."
 },
 {
  "id": "kahoot-struct-comparison",
  "kind": "kahoot",
  "title": "Σύγκριση δομών με ==",
  "source": {
   "title": "Kahoot «Δομές + Αρχεία», «Ταξινόμηση και Δομές»",
   "years": [
    2025
   ]
  },
  "chapters": [
   19
  ],
  "topics": [
   "structs",
   "operators"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "Δεν αποτιμάται",
  "stats": {
   "responses": 151,
   "accuracy": 57
  },
  "label": "Κ19.5",
  "path": "questions/kahoot/kahoot-struct-comparison.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-struct-comparison.html",
  "statement": "Έστω `struct {int x;} cafe = {1}, bar = {2};`. Η παράσταση `cafe == bar` αποτιμάται σε:\n\n- 1\n- 0\n- Δεν αποτιμάται\n- 42\n\n## Συχνή παρανόηση\n\nΤο 24% επέλεξε `0`, υποθέτοντας ότι το `==` συγκρίνει τις δομές πεδίο προς πεδίο, όπως το `=` τις αντιγράφει.",
  "hint": "Η ανάθεση δομών επιτρέπεται, αλλά ελέγξτε ποιοι τελεστές ορίζονται για τύπους δομής· τι θα έλεγε ο μεταγλωττιστής;"
 },
 {
  "id": "kahoot-struct-padding-size",
  "kind": "kahoot",
  "title": "Μέγεθος δομής και padding",
  "source": {
   "title": "Kahoot «Δομές + Αρχεία», «Ταξινόμηση και Δομές»",
   "years": [
    2025
   ]
  },
  "chapters": [
   19
  ],
  "topics": [
   "structs",
   "memory-model",
   "types"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "Εξαρτάται",
  "stats": {
   "responses": 151,
   "accuracy": 52
  },
  "label": "Κ19.6",
  "path": "questions/kahoot/kahoot-struct-padding-size.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-struct-padding-size.html",
  "statement": "Ποιο είναι το μέγεθος του `struct {char c; int x; double d;}`;\n\n- 1 + 4 + 8 = 13\n- 1 + 8 + 8 = 17\n- 4 + 4 + 8 = 16\n- Εξαρτάται\n\n## Συχνή παρανόηση\n\nΤο 24% επέλεξε `4 + 4 + 8 = 16`, την τιμή που δίνει συνήθως ένας 64-bit υπολογιστής· όμως το padding ανάμεσα στα πεδία και τα μεγέθη των τύπων δεν ορίζονται από το πρότυπο.",
  "hint": "Θυμηθείτε ότι ο μεταγλωττιστής μπορεί να προσθέσει padding για τη στοίχιση των πεδίων, και ότι ούτε το `sizeof(int)` είναι ίδιο παντού."
 },
 {
  "id": "kahoot-struct-partial-init",
  "kind": "kahoot",
  "title": "Μερική αρχικοποίηση δομής",
  "source": {
   "title": "Kahoot «Δομές + Αρχεία», «Ταξινόμηση και Δομές»",
   "years": [
    2025
   ]
  },
  "chapters": [
   19
  ],
  "topics": [
   "structs",
   "variables"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "0",
  "stats": {
   "responses": 151,
   "accuracy": 42
  },
  "label": "Κ19.9",
  "path": "questions/kahoot/kahoot-struct-partial-init.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-struct-partial-init.html",
  "statement": "Έστω `struct {int x; int y;} point = {42};`. Ποια είναι η τιμή του `point.y`;\n\n- 42\n- 0\n- 1\n- Ότι έτυχε να έχει η μνήμη σε εκείνη την θέση\n\n## Συχνή παρανόηση\n\nΤο 26% επέλεξε `42`, πιστεύοντας ότι η μία τιμή αντιγράφεται σε όλα τα πεδία, και άλλο 26% «ό,τι έτυχε να έχει η μνήμη», ξεχνώντας ότι με αρχικοποιητή τα πεδία που λείπουν μηδενίζονται.",
  "hint": "Σκεφτείτε τι κάνει η C με τα πεδία που δεν αναφέρονται μέσα σε έναν αρχικοποιητή `{...}`, όπως ακριβώς και στους πίνακες."
 },
 {
  "id": "kahoot-struct-uninitialized",
  "kind": "kahoot",
  "title": "Δομή χωρίς αρχικοποίηση",
  "source": {
   "title": "Kahoot «Δομές + Αρχεία», «Ταξινόμηση και Δομές»",
   "years": [
    2025
   ]
  },
  "chapters": [
   19,
   13
  ],
  "topics": [
   "structs",
   "memory-model",
   "undefined-behavior"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "Ότι έτυχε να έχει η μνήμη σε εκείνη την θέση",
  "stats": {
   "responses": 151,
   "accuracy": 74
  },
  "label": "Κ19.3",
  "path": "questions/kahoot/kahoot-struct-uninitialized.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-struct-uninitialized.html",
  "statement": "Έστω `struct {int x; int y;} point;` (τοπική μεταβλητή). Ποια είναι η τιμή του `point.y`;\n\n- 0xFFFFFFFF\n- 0\n- 1\n- Ότι έτυχε να έχει η μνήμη σε εκείνη την θέση",
  "hint": "Μια τοπική μεταβλητή χωρίς αρχικοποιητή δεν παίρνει καμία τιμή αυτόματα, είτε είναι `int` είτε δομή."
 },
 {
  "id": "kahoot-struct-vs-union",
  "kind": "kahoot",
  "title": "Δομή ή ένωση;",
  "source": {
   "title": "Kahoot «Προχωρημένες Δομές» (διάλεξη 20), «Προχωρημένες Δομές #2»",
   "years": [
    2025
   ]
  },
  "chapters": [
   20,
   19
  ],
  "topics": [
   "unions-enums",
   "structs",
   "memory-model"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "Στην δομή κάθε πεδίο έχει την δική του μνήμη, στην ένωση την μοιράζονται",
  "stats": {
   "responses": 164,
   "accuracy": 63
  },
  "label": "Κ20.3",
  "path": "questions/kahoot/kahoot-struct-vs-union.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-struct-vs-union.html",
  "statement": "Ποια η διαφορά ανάμεσα σε μια δομή (`struct`) και μια ένωση (`union`);\n\n- Στην δομή κάθε πεδίο έχει την δική του μνήμη, στην ένωση την μοιράζονται\n- Η δομή μπορεί να έχει πολλά πεδία, η ένωση μόνο ένα\n- Η δομή μπορεί να έχει άλλες δομές εντός, ενώ η ένωση όχι\n- Trick question, δεν υπάρχει διαφορά",
  "hint": "Συγκρίνετε το `sizeof` μιας δομής και μιας ένωσης με τα ίδια πεδία: τι σας λέει για το πού βρίσκεται κάθε πεδίο;"
 },
 {
  "id": "kahoot-sudo",
  "kind": "kahoot",
  "title": "Δικαιώματα υπερχρήστη",
  "source": {
   "title": "Kahoot «Command Line» (διάλεξη 1)",
   "years": [
    2025
   ]
  },
  "chapters": [
   1
  ],
  "topics": [
   "unix",
   "shell"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "sudo",
  "stats": {
   "responses": 209,
   "accuracy": 68
  },
  "label": "Κ1.5",
  "path": "questions/kahoot/kahoot-sudo.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-sudo.html",
  "statement": "Ποια εντολή μας δίνει δικαιοδοσία υπερ-χρήστη (root) σε ένα σύστημα Linux;\n\n- `doit`\n- `root`\n- `sudo`\n- Run as Administrator",
  "hint": "Το όνομα της εντολής σημαίνει «κάνε το ως (super)user»: μπαίνει μπροστά από την εντολή που θέλουμε να τρέξουμε με αυξημένα δικαιώματα."
 },
 {
  "id": "kahoot-switch-if-else-equivalence",
  "kind": "kahoot",
  "title": "switch και if-else",
  "source": {
   "title": "Kahoot «Ροή Ελέγχου #2» (διάλεξη 8)",
   "years": [
    2025
   ]
  },
  "chapters": [
   8,
   6
  ],
  "topics": [
   "conditionals"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "True",
  "stats": {
   "responses": 157,
   "accuracy": 46
  },
  "label": "Κ8.3",
  "path": "questions/kahoot/kahoot-switch-if-else-equivalence.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-switch-if-else-equivalence.html",
  "statement": "Οποιοδήποτε πρόγραμμα χρησιμοποιεί `switch` μπορούμε να το μετατρέψουμε σε `if-else` και το αντίστροφο.\n\n- True\n- False\n\n## Συχνή παρανόηση\n\nΤο 53% απάντησε False, επειδή τα `case` δέχονται μόνο ακέραιες σταθερές· όμως μπορούμε να κάνουμε `switch` στην ίδια τη συνθήκη (`switch (x > 3.5)`), που είναι 0 ή 1.",
  "hint": "Η `switch` δέχεται οποιαδήποτε ακέραια έκφραση· τι τιμή έχει μια σύγκριση όπως `x > 3.5`;"
 },
 {
  "id": "kahoot-tree-levels-nodes",
  "kind": "kahoot",
  "title": "Κόμβοι δέντρου με n επίπεδα",
  "source": {
   "title": "Kahoot «Λίστες, Δέντρα and Beyond»",
   "years": [
    2025
   ]
  },
  "chapters": [
   22
  ],
  "topics": [
   "trees"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "Εξαρτάται",
  "stats": {
   "responses": 93,
   "accuracy": 53
  },
  "label": "Κ22.4",
  "path": "questions/kahoot/kahoot-tree-levels-nodes.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-tree-levels-nodes.html",
  "statement": "Έχω ένα δέντρο με n επίπεδα. Πόσους κόμβους έχει;\n\n- 2^n\n- log n\n- n\n- Εξαρτάται\n\n## Συχνή παρανόηση\n\nΤο 37% επέλεξε `2^n`, που είναι μόνο το μέγιστο για ένα τέλειο δυαδικό δέντρο· ένα τυχαίο δέντρο μπορεί να έχει από έναν κόμβο ανά επίπεδο μέχρι πολύ περισσότερους.",
  "hint": "Η ερώτηση δεν λέει τι είδους δέντρο είναι· σκεφτείτε ένα εκφυλισμένο δέντρο και ένα τέλειο με τα ίδια επίπεδα."
 },
 {
  "id": "kahoot-tree-min-depth",
  "kind": "kahoot",
  "title": "Ελάχιστο βάθος δυαδικού δέντρου",
  "source": {
   "title": "Kahoot «Προχωρημένες Δομές #2»",
   "years": [
    2025
   ]
  },
  "chapters": [
   22
  ],
  "topics": [
   "trees",
   "complexity"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "O(log n)",
  "stats": {
   "responses": 58,
   "accuracy": 47
  },
  "label": "Κ22.5",
  "path": "questions/kahoot/kahoot-tree-min-depth.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-tree-min-depth.html",
  "statement": "Έστω ένα δυαδικό δέντρο (binary tree) με n στοιχεία. Το ελάχιστο δυνατό βάθος του δέντρου είναι:\n\n- O(n)\n- O(f(x))\n- O(log n)\n- O(1)",
  "hint": "Για να είναι το βάθος ελάχιστο, κάθε επίπεδο πρέπει να είναι γεμάτο· πόσα επίπεδα χρειάζονται για n κόμβους αν κάθε επίπεδο διπλασιάζεται;"
 },
 {
  "id": "kahoot-two-kinds-of-scope",
  "kind": "kahoot",
  "title": "Δύο είδη εμβέλειας",
  "source": {
   "title": "Kahoot «Δυαδική Αναζήτηση, Ταξινόμηση, Πολυπλοκότητα και άλλα» και «Εμβέλεια, Μνήμη και Συμβολοσειρές» (διάλεξη 14)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   14
  ],
  "topics": [
   "scope"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "True",
  "stats": {
   "responses": 127,
   "accuracy": 63
  },
  "label": "Κ14.2",
  "path": "questions/kahoot/kahoot-two-kinds-of-scope.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-two-kinds-of-scope.html",
  "statement": "Στη C υπάρχουν μόνο δύο είδη εμβέλειας για μεταβλητές: τοπικές και παγκόσμιες.\n\n- True\n- False\n\n## Συχνή παρανόηση\n\nΤο 31% απάντησε False, πιθανόν θεωρώντας τις `static` μεταβλητές τρίτο είδος εμβέλειας· η `static` αλλάζει τον χρόνο ζωής και τη μνήμη, όχι το από πού είναι ορατή μια τοπική μεταβλητή.",
  "hint": "Η εμβέλεια εξαρτάται από το σημείο της δήλωσης· ξεχωρίστε την από τον χρόνο ζωής και από τη μνήμη όπου αποθηκεύεται μια μεταβλητή."
 },
 {
  "id": "kahoot-two-pow-64",
  "kind": "kahoot",
  "title": "Πόσο είναι το 2^64",
  "source": {
   "title": "Kahoot «Μεταβλητές και Μνήμη», «Μεταβλητές και Συναρτήσεις» (διάλεξη 2)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "integer-representation"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "$10^{20}$",
  "stats": {
   "responses": 301,
   "accuracy": 38
  },
  "label": "Κ2.12",
  "path": "questions/kahoot/kahoot-two-pow-64.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-two-pow-64.html",
  "statement": "Πόσο μεγάλος αριθμός είναι περίπου το $2^{64}$;\n\n- $10^{10}$\n- $10^{20}$\n- $10^{30}$\n- 42\n\n## Συχνή παρανόηση\n\nΤο 48% απάντησε $10^{30}$, υπερεκτιμώντας κατά 10 τάξεις μεγέθους· με $2^{10} \\approx 10^3$, το $2^{64}$ είναι περίπου $1.8 \\cdot 10^{19}$.",
  "hint": "Χρησιμοποιήστε την προσέγγιση $2^{10} = 1024 \\approx 10^3$ και γράψτε το $2^{64}$ ως $2^4 \\cdot (2^{10})^6$."
 },
 {
  "id": "kahoot-typedef-array-size",
  "kind": "kahoot",
  "title": "sizeof ενός typedef πίνακα",
  "source": {
   "title": "Kahoot «Δομές + Αρχεία», «Ταξινόμηση και Δομές»",
   "years": [
    2025
   ]
  },
  "chapters": [
   19,
   10
  ],
  "topics": [
   "structs",
   "types",
   "arrays"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "8192",
  "stats": {
   "responses": 151,
   "accuracy": 66
  },
  "label": "Κ19.4",
  "path": "questions/kahoot/kahoot-typedef-array-size.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-typedef-array-size.html",
  "statement": "Έστω `typedef double trouble[1024];` και `sizeof(double) == 8`. Ποιο είναι το `sizeof(trouble)`;\n\n- 1024\n- 4096\n- 8192\n- Εξαρτάται\n\n## Συχνή παρανόηση\n\nΤο 24% επέλεξε «Εξαρτάται», ενώ το `typedef` απλώς δίνει όνομα στον τύπο «πίνακας 1024 `double`», που έχει σταθερό μέγεθος.",
  "hint": "Το `typedef` δεν φτιάχνει μεταβλητή, μόνο ένα συνώνυμο για τον τύπο· ποιος είναι αυτός ο τύπος και πόσα bytes πιάνει;"
 },
 {
  "id": "kahoot-typedef-purpose",
  "kind": "kahoot",
  "title": "Σε τι χρησιμεύει το typedef",
  "source": {
   "title": "Kahoot «Δομές + Αρχεία», «Ταξινόμηση και Δομές»",
   "years": [
    2025
   ]
  },
  "chapters": [
   19
  ],
  "topics": [
   "structs",
   "types"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "Για να ορίσουμε συνώνυμα τύπων",
  "stats": {
   "responses": 151,
   "accuracy": 79
  },
  "label": "Κ19.2",
  "path": "questions/kahoot/kahoot-typedef-purpose.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-typedef-purpose.html",
  "statement": "Σε τι χρησιμοποιούμε το `typedef` στην C;\n\n- Για να ορίσουμε συνώνυμα τύπων\n- Για να ορίσουμε μεταβλητές\n- Για να διαγράψουμε από την μνήμη ένα struct\n- Για να γράψουμε λίγο παραπάνω κώδικα",
  "hint": "Μετά από `typedef struct point Point;` τι σημαίνει η λέξη `Point`;"
 },
 {
  "id": "kahoot-uint64-range",
  "kind": "kahoot",
  "title": "Πόσους αριθμούς χωράει ένας uint64_t",
  "source": {
   "title": "Kahoot «Μεταβλητές και Μνήμη», «Μεταβλητές και Συναρτήσεις» (διάλεξη 2)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "integer-representation",
   "types"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "$2^{64}$",
  "stats": {
   "responses": 301,
   "accuracy": 57
  },
  "label": "Κ2.9",
  "path": "questions/kahoot/kahoot-uint64-range.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-uint64-range.html",
  "statement": "Πόσους διαφορετικούς αριθμούς μπορώ να αναπαραστήσω με έναν `uint64_t`;\n\n- $2^{64}$\n- 4 δις\n- Όλους τους ακεραίους\n- Εξαρτάται",
  "hint": "Το όνομα του τύπου από το `stdint.h` λέει ακριβώς πόσα bits έχει, σε αντίθεση με τον `int`."
 },
 {
  "id": "kahoot-union-purpose",
  "kind": "kahoot",
  "title": "Σε τι χρησιμεύει η ένωση",
  "source": {
   "title": "Kahoot «Προχωρημένες Δομές» (διάλεξη 20), «Προχωρημένες Δομές #2»",
   "years": [
    2025
   ]
  },
  "chapters": [
   20
  ],
  "topics": [
   "unions-enums",
   "memory-model"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "Εξοικονομεί χώρο μνήμης",
  "stats": {
   "responses": 164,
   "accuracy": 65
  },
  "label": "Κ20.2",
  "path": "questions/kahoot/kahoot-union-purpose.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-union-purpose.html",
  "statement": "Σε τι χρησιμεύει η ένωση (`union`);\n\n- Είναι ο μόνος τρόπος να δεσμεύσουμε χώρο για πίνακες\n- Θέτει όριο στον αριθμό των πεδίων μιας δομής\n- Είναι εξαιρετική ομάδα\n- Εξοικονομεί χώρο μνήμης",
  "hint": "Μια ένωση κρατάει μία τιμή τη φορά από πολλούς πιθανούς τύπους· τι κερδίζουμε σε σχέση με μια δομή με όλα αυτά τα πεδία;"
 },
 {
  "id": "kahoot-union-size",
  "kind": "kahoot",
  "title": "Μέγεθος ένωσης",
  "source": {
   "title": "Kahoot «Προχωρημένες Δομές» (διάλεξη 20), «Προχωρημένες Δομές #2»",
   "years": [
    2025
   ]
  },
  "chapters": [
   20
  ],
  "topics": [
   "unions-enums",
   "memory-model"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "max(sizeof(x), sizeof(name), sizeof(double))",
  "stats": {
   "responses": 164,
   "accuracy": 36
  },
  "label": "Κ20.8",
  "path": "questions/kahoot/kahoot-union-size.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-union-size.html",
  "statement": "Έστω `union station {int x; char name[20]; double d;};`. Ποιο είναι το `sizeof(union station)`;\n\n- sizeof(double)\n- sizeof(int) + sizeof(name) + sizeof(double)\n- max(sizeof(x), sizeof(name), sizeof(double))\n- 42\n\n## Συχνή παρανόηση\n\nΤο 22% επέλεξε `sizeof(double)`, θεωρώντας τον `double` το μεγαλύτερο πεδίο, ενώ ο πίνακας `name` πιάνει 20 bytes· και το 18% πρόσθεσε τα μεγέθη, όπως σε μια δομή.",
  "hint": "Σε μια ένωση όλα τα πεδία ξεκινούν από την ίδια διεύθυνση· πόσος χώρος χρειάζεται ώστε να χωράει οποιοδήποτε από αυτά;"
 },
 {
  "id": "kahoot-unsigned-sum-sign",
  "kind": "kahoot",
  "title": "Άθροισμα θετικών unsigned int",
  "source": {
   "title": "Kahoot «Μεταβλητές και Μνήμη», «Μεταβλητές και Συναρτήσεις» (διάλεξη 2)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "integer-representation",
   "types"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "Ναι",
  "stats": {
   "responses": 301,
   "accuracy": 63
  },
  "label": "Κ2.7",
  "path": "questions/kahoot/kahoot-unsigned-sum-sign.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-unsigned-sum-sign.html",
  "statement": "Αν προσθέσω δύο θετικούς αριθμούς τύπου `unsigned int`, το αποτέλεσμα είναι πάντα θετικό;\n\n- Ναι\n- Όχι\n\n## Συχνή παρανόηση\n\nΤο 30% απάντησε «Όχι», μεταφέροντας τη συμπεριφορά του `int` (όπου η υπερχείλιση δίνει αρνητικό) στους unsigned· ένας `unsigned int` αναδιπλώνεται modulo $2^{32}$ και δεν γίνεται ποτέ αρνητικός (αυστηρά, μπορεί να βγει 0 ή μικρότερος από τους προσθετέους).",
  "hint": "Ποιες τιμές μπορεί να αναπαραστήσει καθόλου ένας `unsigned int`; Υπάρχει στο εύρος του κάποιος αρνητικός;"
 },
 {
  "id": "kahoot-uptime",
  "kind": "kahoot",
  "title": "Φορτίο απομακρυσμένου server",
  "source": {
   "title": "Kahoot «Command Line» (διάλεξη 1)",
   "years": [
    2025
   ]
  },
  "chapters": [
   1
  ],
  "topics": [
   "shell",
   "unix"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "uptime",
  "stats": {
   "responses": 209,
   "accuracy": 53
  },
  "label": "Κ1.8",
  "path": "questions/kahoot/kahoot-uptime.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-uptime.html",
  "statement": "Netflix Interview Question: Με ποια εντολή θα έλεγχες το workload ενός απομακρυσμένου server;\n\n- `ls`\n- `uptime`\n- `cat`\n- `users`",
  "hint": "Σκεφτείτε ποια από τις βασικές εντολές δείχνει, εκτός από την ώρα, και πόσο «απασχολημένο» είναι το σύστημα."
 },
 {
  "id": "kahoot-valgrind",
  "kind": "kahoot",
  "title": "Εργαλείο για memory leaks",
  "source": {
   "title": "Kahoot «Δυαδική Αναζήτηση και Ταξινόμηση» (διάλεξη 17)",
   "years": [
    2025
   ]
  },
  "chapters": [
   21,
   13
  ],
  "topics": [
   "debugging",
   "dynamic-memory"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "Valgrind",
  "stats": {
   "responses": 71,
   "accuracy": 86
  },
  "label": "Κ21.2",
  "path": "questions/kahoot/kahoot-valgrind.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-valgrind.html",
  "statement": "Το εργαλείο που μας βοηθάει να βρούμε memory leaks στο πρόγραμμά μας λέγεται:\n\n- Grindenwald\n- Valhalla\n- Valgrind\n- Mjölnir",
  "hint": "Είναι το εργαλείο που τρέχει το πρόγραμμά σας και στο τέλος αναφέρει μνήμη «definitely lost»."
 },
 {
  "id": "kahoot-variable-increment-via-ptr",
  "kind": "kahoot",
  "title": "Αλλαγή μεταβλητής και δείκτης",
  "source": {
   "title": "Kahoot «Δείκτες και Αναδρομή» (διάλεξη 11)",
   "years": [
    2025
   ]
  },
  "chapters": [
   11
  ],
  "topics": [
   "pointers",
   "variables"
  ],
  "difficulty": 2,
  "type": "multiple-choice",
  "answer": "42",
  "stats": {
   "responses": 152,
   "accuracy": 48
  },
  "label": "Κ11.7",
  "path": "questions/kahoot/kahoot-variable-increment-via-ptr.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-variable-increment-via-ptr.html",
  "statement": "Τι θα τυπώσει ο παρακάτω κώδικας;\n\n```c\nint x = 41;\nint *ptr = &x;\nx++;\nprintf(\"%d\", *ptr);\n```\n\n- `41`\n- `42`\n- `43`\n- Που να ξέρω",
  "hint": "Ο δείκτης δεν κρατά αντίγραφο της τιμής του `x` αλλά τη διεύθυνσή του."
 },
 {
  "id": "kahoot-volatile-memory",
  "kind": "kahoot",
  "title": "Κύρια και δευτερεύουσα μνήμη",
  "source": {
   "title": "Kahoot «Μεταβλητές και Μνήμη», «Μεταβλητές και Συναρτήσεις» (διάλεξη 2)",
   "years": [
    2024,
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "computers",
   "memory-model"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "Δευτερεύουσα μνήμη",
  "stats": {
   "responses": 301,
   "accuracy": 84
  },
  "label": "Κ2.3",
  "path": "questions/kahoot/kahoot-volatile-memory.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-volatile-memory.html",
  "statement": "Μόλις έπεσε το ρεύμα, τα δεδομένα σου διατηρήθηκαν μόνο αν τα έσωσες στην\n\n- Κύρια μνήμη\n- Δευτερεύουσα μνήμη",
  "hint": "Ποια από τις δύο χρειάζεται ρεύμα για να κρατήσει τα περιεχόμενά της;"
 },
 {
  "id": "kahoot-while-as-for",
  "kind": "kahoot",
  "title": "while γραμμένο ως for",
  "source": {
   "title": "Kahoot «Τελεστές, Εντολές και Ροή Ελέγχου» (διάλεξη 6)",
   "years": [
    2025
   ]
  },
  "chapters": [
   6
  ],
  "topics": [
   "loops"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "for(; condition;) statement;",
  "stats": {
   "responses": 245,
   "accuracy": 24
  },
  "label": "Κ6.7",
  "path": "questions/kahoot/kahoot-while-as-for.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-while-as-for.html",
  "statement": "Το loop `while (condition) statement;` είναι ισοδύναμο με:\n\n- `for(condition ; ; statement);`\n- `for(; condition ; statement);`\n- `for(; condition;) statement;`\n- `for(;;condition) statement;`\n\n## Συχνή παρανόηση\n\nΤο 34% επέλεξε `for(; condition ; statement);`· αυτό δουλεύει μόνο αν το `statement` είναι απλή έκφραση, αφού το τρίτο μέρος της `for` δέχεται έκφραση και όχι οποιαδήποτε εντολή (π.χ. ένα μπλοκ `{…}` ή ένα `if`).",
  "hint": "Η `for` έχει τρία μέρη (αρχικοποίηση, συνθήκη, βήμα) και σώμα· αντιστοιχίστε σε καθένα τι έχει η `while`."
 },
 {
  "id": "kahoot-while-not-42",
  "kind": "kahoot",
  "title": "while(!42)",
  "source": {
   "title": "Kahoot «Επίλυση Προβλημάτων» (διάλεξη 7)",
   "years": [
    2025
   ]
  },
  "chapters": [
   6,
   5
  ],
  "topics": [
   "loops",
   "operators"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "0 φορές",
  "stats": {
   "responses": 192,
   "accuracy": 17
  },
  "label": "Κ6.9",
  "path": "questions/kahoot/kahoot-while-not-42.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-while-not-42.html",
  "statement": "Η εντολή `while (!42) printf(\"yes\\n\");` θα τυπώσει `yes`:\n\n- 0 φορές\n- 42 φορές\n- άπειρες φορές\n- Δεν είναι έγκυρη C\n\n## Συχνή παρανόηση\n\nΤο 53% απάντησε ότι δεν είναι έγκυρη C, πιστεύοντας ότι η συνθήκη πρέπει να είναι σύγκριση· στην C κάθε ακέραια έκφραση είναι συνθήκη, και το `!42` κάνει 0.",
  "hint": "Η συνθήκη της `while` μπορεί να είναι οποιαδήποτε έκφραση· υπολογίστε την τιμή της `!42` θυμούμενοι ποιες τιμές η C θεωρεί αληθείς."
 },
 {
  "id": "kahoot-while-predecrement-overflow",
  "kind": "kahoot",
  "title": "while(--i) με i = 0",
  "source": {
   "title": "Kahoot «Επίλυση Προβλημάτων» (διάλεξη 7)",
   "years": [
    2025
   ]
  },
  "chapters": [
   8,
   6
  ],
  "topics": [
   "loops",
   "integer-representation"
  ],
  "difficulty": 3,
  "type": "multiple-choice",
  "answer": "Μετά από κάποια δευτερόλεπτα εκτέλεσης, ένα @",
  "stats": {
   "responses": 192,
   "accuracy": 17
  },
  "label": "Κ8.5",
  "path": "questions/kahoot/kahoot-while-predecrement-overflow.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-while-predecrement-overflow.html",
  "statement": "Παλιό θέμα (δύσκολο): τι θα εκτυπωθεί από το πρόγραμμα;\n\n```c\nint i = 0;\nwhile (--i);\nprintf(\"@\");\n```\n\n- Σχεδόν ακαριαία, ένα @\n- Μετά από κάποια δευτερόλεπτα εκτέλεσης, ένα @\n- Θα εκτυπώνει συνεχώς @, επ' άπειρον\n- Hello 42 World\n\n## Συχνή παρανόηση\n\nΤο 43% απάντησε ότι θα τυπώνει @ επ' άπειρον, χάνοντας ότι το `;` είναι η (κενή) εντολή του βρόχου και ότι το `i` κάποτε υπερχειλίζει και φτάνει ξανά στο 0.",
  "hint": "Προσέξτε το ερωτηματικό αμέσως μετά τη `while`, και σκεφτείτε τι γίνεται όταν ένας `int` μειώνεται ξανά και ξανά πέρα από την ελάχιστη τιμή του."
 },
 {
  "id": "kahoot-while-vs-do-while",
  "kind": "kahoot",
  "title": "while και do-while",
  "source": {
   "title": "Kahoot «Τελεστές, Εντολές και Ροή Ελέγχου» (διάλεξη 6)",
   "years": [
    2025
   ]
  },
  "chapters": [
   6
  ],
  "topics": [
   "loops"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "answer": "False",
  "stats": {
   "responses": 245,
   "accuracy": 85
  },
  "label": "Κ6.2",
  "path": "questions/kahoot/kahoot-while-vs-do-while.md",
  "url": "https://progintro.github.io/study/questions/kahoot/kahoot-while-vs-do-while.html",
  "statement": "Τα `while` και `do-while` loops είναι το ίδιο πράγμα;\n\n- True\n- False",
  "hint": "Σκεφτείτε πότε ελέγχεται η συνθήκη σε κάθε βρόχο και τι γίνεται αν είναι ψευδής από την αρχή."
 },
 {
  "id": "lab-lab00-about",
  "kind": "lab",
  "title": "Στοιχεία φοιτητή (Παλιό θέμα)",
  "source": {
   "title": "Εργαστήριο 0, Άσκηση 1",
   "url": "https://progintro.github.io/lab-material/labs/lab00/",
   "years": [
    2025
   ]
  },
  "chapters": [
   2,
   0
  ],
  "topics": [
   "input-output",
   "compilation"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α2.9",
  "path": "questions/labs/lab-lab00-about.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab00-about.html",
  "statement": "Γράψτε ένα πρόγραμμα `about` το οποίο τυπώνει 3 γραμμές στην πρότυπη έξοδο (stdout):\n1) το όνομά σας με λατινικούς χαρακτήρες στην 1η, 2) το sdi σας στην 2η και 3)\n`I'm 100% \"ready\"!` στην 3η. Παράδειγμα εξόδου από την εκτέλεση του προγράμματος\n`about`:\n\n```text\n$ ./about\nMichael Jordan\nsdi2300999\nI'm 100% \"ready\"!\n$\n```",
  "hint": "Το δύσκολο σημείο είναι η τρίτη γραμμή: τα διπλά εισαγωγικά κλείνουν τη συμβολοσειρά\nτης `printf` και το `%` ξεκινά προδιαγραφή μορφοποίησης. Σκεφτείτε πώς «αποδρά» κανείς\nέναν χαρακτήρα μέσα σε συμβολοσειρά και πώς τυπώνεται ένα σκέτο `%`. Μην ξεχάσετε την\nαλλαγή γραμμής στο τέλος κάθε γραμμής."
 },
 {
  "id": "lab-lab00-overflow",
  "kind": "lab",
  "title": "Υπερχείλιση ακεραίων",
  "source": {
   "title": "Εργαστήριο 0, Άσκηση 2",
   "url": "https://progintro.github.io/lab-material/labs/lab00/",
   "years": [
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "integer-representation",
   "types",
   "input-output"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α2.10",
  "path": "questions/labs/lab-lab00-overflow.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab00-overflow.html",
  "statement": "Μεταγλωττίστε και τρέξτε το ακόλουθο πρόγραμμα:\n\n```c\n#include <stdio.h>\n\nint main() {\n  printf(\"%d\\n\", 2000000000 + 2000000000);\n  return 0;\n}\n```\n\nΣυμπεριφέρεται όπως θα περιμένατε; Γιατί / γιατί όχι; Διορθώστε το αν μπορείτε.\n\n**2.1 Ειδικές ακολουθίες χαρακτήρων (Προχωρημένο, Προαιρετικό)**\n\nΠαραπάνω χρησιμοποιήσαμε την ειδική ακολουθία `\\n` για να τυπώσουμε μια νέα γραμμή\nμετά το μήνυμά μας. Αντίστοιχα μπορούμε να χρησιμοποιήσουμε άλλες ακολουθίες προκειμένου\nνα τυπώσουμε ειδικούς χαρακτήρες ή να δώσουμε συγκεκριμένη μορφοποίηση στο κείμενό μας.\n\n**Παράδειγμα 1.** Δοκιμάστε να τυπώσετε την ειδική ακολουθία `\\U0001F525`. Τι τυπώνεται\nστην κονσόλα; Μπορείτε να βρείτε μια εκτενή λίστα με άλλες ειδικές ακολουθίες\n[εδώ](https://unicode.org/emoji/charts/full-emoji-list.html) ενώ για να μάθετε\nπερισσότερα μπορείτε να διαβάσετε για Unicode χαρακτήρες στην\n[wikipedia](https://en.wikipedia.org/wiki/List_of_Unicode_characters).\n\n**Παράδειγμα 2.** Χρησιμοποιήστε την `printf` για να τυπώσετε την ακολουθία\n`\"Hello \\033[1m world \\033[0m !\"`. Τι παρατηρείτε; Μπορείτε να φανταστείτε τι σημαίνουν\nοι ακολουθίες `\\033[1m` και `\\033[0m`; Τι συμβαίνει αν αντικαταστήσετε την ακολουθία\n`\\033[1m` με την ακολουθία `\\033[5m`; Μπορείτε να μάθετε περισσότερα διαβάζοντας για\n[ANSI Escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code).",
  "hint": "Ποιος είναι ο τύπος των δύο σταθερών και ποια είναι η μεγαλύτερη τιμή που χωράει σε\nέναν `int` των 4 bytes; Διαβάστε και τις προειδοποιήσεις του `gcc`. Για τη διόρθωση,\nσκεφτείτε έναν ευρύτερο ακέραιο τύπο και ποια προδιαγραφή της `printf` του αντιστοιχεί."
 },
 {
  "id": "lab-lab01-info",
  "kind": "lab",
  "title": "Το πρώτο σας repository",
  "source": {
   "title": "Εργαστήριο 1, Άσκηση 1",
   "url": "https://progintro.github.io/lab-material/labs/lab01/",
   "years": [
    2025
   ]
  },
  "chapters": [
   4,
   1
  ],
  "topics": [
   "git"
  ],
  "difficulty": 1,
  "type": "tooling",
  "label": "Α4.11",
  "path": "questions/labs/lab-lab01-info.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab01-info.html",
  "statement": "Πατήστε τον [ακόλουθο σύνδεσμο](https://classroom.github.com/a/8_3_scjJ) για να\nδημιουργήσετε το δικό σας repository `progintro/lab01-YourGitHub` και πραγματοποιήστε τα\nακόλουθα βήματα:\n\n1. Κατεβάστε το repository τοπικά τρέχοντας την εντολή:\n\n```text\n$ git clone git@github.com:progintro/lab01-YourGitHub\nCloning into 'lab01-ethan42'...\nremote: Enumerating objects: 3, done.\nremote: Counting objects: 100% (3/3), done.\nremote: Compressing objects: 100% (2/2), done.\nReceiving objects: 100% (3/3), 5.10 KiB | 871.00 KiB/s, done.\nremote: Total 3 (delta 0), reused 2 (delta 0), pack-reused 0 (from 0)\n```\n\n2. Μέσα στον φάκελο `lab01-YourGitHub` που δημιούργησε η παραπάνω εντολή, προσθέστε ένα\n   αρχείο `info.txt` με τα ακόλουθα στοιχεία:\n\n```text\nΌνομα, Επώνυμο, sdiXXYYYYY (εφόσον έχετε)\n```\n\n3. Προσθέστε το αρχείο σας στο repository χρησιμοποιώντας την εντολή `git add`:\n\n```text\ngit add info.txt\n```\n\n4. Τρέξτε την εντολή `git commit` για να μονιμοποιήσετε τις αλλαγές σας:\n\n```text\ngit commit\n```\n\n5. Τρέξτε την εντολή `git push` για να ανεβάσετε τις αλλαγές σας στο GitHub.\n\n```text\n$ git push\nEnumerating objects: 4, done.\nCounting objects: 100% (4/4), done.\nDelta compression using up to 4 threads\nCompressing objects: 100% (2/2), done.\nWriting objects: 100% (3/3), 319 bytes | 63.00 KiB/s, done.\nTotal 3 (delta 0), reused 0 (delta 0)\nTo github.com:progintro/lab01-ethan42\n   4ef457c..aa9f709  main -> main\n```\n\nΕπιβεβαιώστε ότι βλέπετε τις αλλαγές πηγαίνοντας στο αντίστοιχο link του repository σας:\n[https://github.com/progintro/lab01-YourGitHub](https://github.com/progintro/lab01-YourGitHub).",
  "hint": "Το `git clone` με διεύθυνση `git@github.com:` χρησιμοποιεί ssh, οπότε πρέπει πρώτα να\nέχετε προσθέσει το δημόσιο κλειδί σας στο GitHub και να έχετε ρυθμίσει `user.name` και\n`user.email`. Θυμηθείτε τα τρία στάδια: `add` (προετοιμασία), `commit` (τοπική\nκαταγραφή), `push` (αποστολή στο GitHub). Με `git status` βλέπετε σε ποιο στάδιο είστε."
 },
 {
  "id": "lab-lab01-step1-navigation",
  "kind": "lab",
  "title": "Πλοήγηση στο σύστημα αρχείων",
  "source": {
   "title": "Εργαστήριο 1, Βήμα 1",
   "url": "https://progintro.github.io/lab-material/labs/lab01/",
   "years": [
    2025
   ]
  },
  "chapters": [
   1
  ],
  "topics": [
   "shell",
   "unix"
  ],
  "difficulty": 1,
  "type": "tooling",
  "label": "Α1.6",
  "path": "questions/labs/lab-lab01-step1-navigation.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab01-step1-navigation.html",
  "statement": "Σε ένα από τα μηχανήματα Linux του εργαστηρίου, εκτελέστε με τη σειρά:\n\n**1.** Εμφανίστε τα περιεχόμενα του καταλόγου /usr/include.\n\n**2.** Εμφανίστε το πλήρες όνομα του τρέχοντος καταλόγου.\n\n**3.** Δημιουργήστε κάτω από τον τρέχοντα κατάλογο ένα νέο κατάλογο με όνομα myWork.\n\n**4.** Μεταβείτε σε αυτόν τον νέο κατάλογο.",
  "hint": "Χρειάζεστε τέσσερις εντολές: μία για λίστα περιεχομένων, μία για τον τρέχοντα κατάλογο,\nμία για δημιουργία καταλόγου και μία για αλλαγή καταλόγου. Προσέξτε τη διαφορά απόλυτου\nμονοπατιού (ξεκινά από `/`) και σχετικού μονοπατιού, και ότι τα ονόματα είναι\ncase-sensitive."
 },
 {
  "id": "lab-lab01-step2-compile-link",
  "kind": "lab",
  "title": "Μεταγλώττιση, σύνδεση και εκτέλεση",
  "source": {
   "title": "Εργαστήριο 1, Βήμα 2",
   "url": "https://progintro.github.io/lab-material/labs/lab01/",
   "years": [
    2025
   ]
  },
  "chapters": [
   1,
   0
  ],
  "topics": [
   "compilation",
   "shell"
  ],
  "difficulty": 1,
  "type": "tooling",
  "label": "Α1.7",
  "path": "questions/labs/lab-lab01-step2-compile-link.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab01-step2-compile-link.html",
  "statement": "Συνεχίζοντας μέσα στον κατάλογο myWork:\n\n**5.** Αντιγράψτε στον κατάλογο αυτό το πηγαίο αρχείο `~iphw/samples/mysin.c`\n\n**6.** Δημιουργήστε το εκτελέσιμο αρχείο mysin από το πηγαίο αρχείο που μόλις\nαντιγράψατε.\n\n**7.** Τρέξτε το εκτελέσιμο αυτό.\n\n**8.** Αντιγράψτε στον τρέχοντα κατάλογο το πηγαίο αρχείο `~iphw/samples/mymain.c`\n(διατηρήστε το όνομα `mymain.c`).\n\n**9.** Αντιγράψτε στον τρέχοντα κατάλογο το αντικειμενικό αρχείο\n`~iphw/samples/myfunct.o`\n\n**10.** Μεταγλωττίστε το πηγαίο αρχείο `mymain.c` στο αντίστοιχο αντικειμενικό αρχείο.\n\n**11.** Συνδέστε το αντικειμενικό αρχείο που κατασκευάσατε και το αντικειμενικό αρχείο\nmyfunct.o δημιουργώντας το εκτελέσιμο αρχείο myprog.\n\n**12.** Εκτελέστε το myprog και ακολουθήστε τις οδηγίες που θα εκτυπωθούν.\n\n**13.** Διαγράψτε όλα τα αρχεία που δημιουργήσατε καθώς και τον κατάλογο myWork.",
  "hint": "Το `mysin.c` χρησιμοποιεί τη μαθηματική βιβλιοθήκη, οπότε η σύνδεση θέλει την κατάλληλη\nεπιλογή του `gcc`. Διακρίνετε τα δύο στάδια: με `-c` παίρνετε αντικειμενικό αρχείο `.o`,\nκαι με `-o` πάνω σε αντικειμενικά αρχεία τα συνδέετε σε εκτελέσιμο. Για να διαγράψετε\nτον κατάλογο πρέπει πρώτα να βγείτε από αυτόν."
 },
 {
  "id": "lab-lab01-step3-copy-view",
  "kind": "lab",
  "title": "Αντιγραφή, μετονομασία και προβολή αρχείων",
  "source": {
   "title": "Εργαστήριο 1, Βήμα 3",
   "url": "https://progintro.github.io/lab-material/labs/lab01/",
   "years": [
    2025
   ]
  },
  "chapters": [
   1
  ],
  "topics": [
   "shell",
   "unix"
  ],
  "difficulty": 1,
  "type": "tooling",
  "label": "Α1.8",
  "path": "questions/labs/lab-lab01-step3-copy-view.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab01-step3-copy-view.html",
  "statement": "**14.** Αντιγράψτε στον τρέχοντα κατάλογο το αρχείο `stdio.h` από τον κατάλογο\n`/usr/include`\n\n**15.** Μετονομάστε το αρχείο που αντιγράψατε σε `Mystdio.h`\n\n**16.** Εμφανίστε στην οθόνη τα περιεχόμενα του αρχείου αυτού.",
  "hint": "Ο τρέχων κατάλογος γράφεται σύντομα ως `.`. Η μετονομασία στο Unix είναι «μετακίνηση»\nμε νέο όνομα. Για την προβολή, δοκιμάστε και την επιλογή που αριθμεί τις γραμμές."
 },
 {
  "id": "lab-lab01-step4-permissions",
  "kind": "lab",
  "title": "Δικαιώματα προστασίας",
  "source": {
   "title": "Εργαστήριο 1, Βήμα 4",
   "url": "https://progintro.github.io/lab-material/labs/lab01/",
   "years": [
    2025
   ]
  },
  "chapters": [
   1
  ],
  "topics": [
   "unix",
   "shell"
  ],
  "difficulty": 1,
  "type": "tooling",
  "label": "Α1.9",
  "path": "questions/labs/lab-lab01-step4-permissions.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab01-step4-permissions.html",
  "statement": "**17.** Δημιουργήστε στον τρέχοντα κατάλογο ένα κενό αρχείο με όνομα .my_file (προσέξτε\nτην τελεία στην αρχή του ονόματος).\n\n**18.** Εμφανίστε τα δικαιώματα προστασίας του αρχείου αυτού και όποιες άλλες χρήσιμες\nπληροφορίες μας δίνει το λειτουργικό σύστημα για αυτό.\n\n**19.** Αλλάξτε τα δικαιώματα προστασίας έτσι ώστε εσείς (ο ιδιοκτήτης του) να έχετε\nόλα τα δικαιώματα προστασίας (ανάγνωσης, εγγραφής και εκτέλεσης), τα μέλη της ομάδας\nστην οποία ανήκει το αρχείο να έχουν δικαιώματα ανάγνωσης και εκτέλεσης και οι υπόλοιποι\nνα έχουν μόνο δικαίωμα ανάγνωσης.\n\n**20.** Εμφανίστε πάλι τα δικαιώματα προστασίας του αρχείου .my_file (και τις άλλες\nπληροφορίες).\n\n**21.** Εμφανίστε όλα τα αρχεία του τρέχοντος καταλόγου, μαζί με τα δικαιώματα\nπροστασίας (και τις άλλες πληροφορίες), μη συμπεριλαμβανομένων των αρχείων που το όνομά\nτους αρχίζει από τελεία.\n\n**22.** Το ίδιο με το προηγούμενο, αλλά να συμπεριληφθούν και τα αρχεία που το όνομά\nτους αρχίζει από τελεία.",
  "hint": "Τα δικαιώματα της `chmod` είναι τρία οκταδικά ψηφία (ιδιοκτήτης, ομάδα, υπόλοιποι), το\nκαθένα άθροισμα των 4 (ανάγνωση), 2 (εγγραφή) και 1 (εκτέλεση). Το `.my_file` είναι\nκρυφό αρχείο: σκεφτείτε ποια επιλογή της `ls` εμφανίζει και τα κρυφά αρχεία."
 },
 {
  "id": "lab-lab01-step5-grep-pipes",
  "kind": "lab",
  "title": "Αναζήτηση, ανακατεύθυνση και σωληνώσεις",
  "source": {
   "title": "Εργαστήριο 1, Βήμα 5",
   "url": "https://progintro.github.io/lab-material/labs/lab01/",
   "years": [
    2025
   ]
  },
  "chapters": [
   1
  ],
  "topics": [
   "redirection",
   "shell",
   "unix"
  ],
  "difficulty": 2,
  "type": "tooling",
  "label": "Α1.10",
  "path": "questions/labs/lab-lab01-step5-grep-pipes.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab01-step5-grep-pipes.html",
  "statement": "**23.** Μέσω της εντολής `man` ενημερωθείτε σχετικά με τις δυνατότητες της εντολής grep.\n\n**24.** Χρησιμοποιήστε την εντολή `grep` για να βρείτε μέσα στο αρχείο\n`/usr/include/stdlib.h` τις γραμμές που περιλαμβάνουν το κείμενο size.\n\n**25.** Επαναλάβετε την προηγούμενη εντολή αλλά να κάνετε ανακατεύθυνση της εξόδου της\nστο αρχείο grepout.txt\n\n**26.** Συνδυάστε με κάποιον τρόπο τις εντολές ls και grep για να βρείτε στον τρέχοντα\nκατάλογο αρχεία στα οποία ο ιδιοκτήτης έχει δικαιώματα ανάγνωσης και εγγραφής, αλλά όχι\nεκτέλεσης και όλοι οι υπόλοιποι δεν έχουν κανένα δικαίωμα.\n\n**27.** Αντιγράψτε στον τρέχοντα κατάλογο το πηγαίο αρχείο `~iphw/samples/capitalize.c`\nδημιουργήστε το αντίστοιχο εκτελέσιμο και τρέξτε το με ανακατεύθυνση της εισόδου από το\nίδιο το πηγαίο αρχείο `capitalize.c` στέλνοντας την έξοδο (πάλι με ανακατεύθυνση) στο\nαρχείο `CAPITALIZE.c`\n\n**28.** Δοκιμάστε να μεταγλωττίσετε το αρχείο `CAPITALIZE.c`. Μην ανησυχείτε όμως αν δεν\nμπορεί να μεταγλωττιστεί (γιατί άραγε;)",
  "hint": "Για το 26, η έξοδος της `ls -l` είναι κείμενο: γράψτε το ζητούμενο μοτίβο δικαιωμάτων\n(π.χ. πώς φαίνεται το «rw- --- ---») και φιλτράρετέ το με `grep` μέσω σωλήνωσης. Για το\n28, σκεφτείτε τι έπαθαν οι λέξεις-κλειδιά της C και τα ονόματα των συναρτήσεων όταν\nέγιναν κεφαλαία."
 },
 {
  "id": "lab-lab02-calc",
  "kind": "lab",
  "title": "Ένα απλό κομπιουτεράκι",
  "source": {
   "title": "Εργαστήριο 2, Άσκηση 1",
   "url": "https://progintro.github.io/lab-material/labs/lab02/",
   "years": [
    2025
   ]
  },
  "chapters": [
   9,
   2
  ],
  "topics": [
   "variables",
   "input-output",
   "types",
   "input-validation"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α9.11",
  "path": "questions/labs/lab-lab02-calc.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab02-calc.html",
  "statement": "Η άσκηση αυτή ίσως σας βοηθήσει και στην Εργασία #0.\n\nΓράψτε ένα πρόγραμμα C `calc.c` που δρα ως ένα κομπιουτεράκι (calculator) για να\nπραγματοποιεί πρόσθεση. Το πρόγραμμά σας πρέπει να ζητά δύο ακεραίους από την πρότυπη\nείσοδο (stdin) και στην συνέχεια να τυπώνει το άθροισμά τους. Παράδειγμα εκτέλεσης\nακολουθεί:\n\n```text\n$ ./calc\nPlease enter the first number: 42\nPlease enter the second number: 58\nThe sum of the two numbers is: 100\n$ echo $?\n0\n```\n\n**1.1 Υψηλή ακρίβεια (Προχωρημένο, Προαιρετικό)**\n\nΤροποποιήστε το παραπάνω πρόγραμμα προκειμένου να μπορεί να δέχεται μεγάλους αριθμούς\nμέχρι και $10^{18}$. Το πρόγραμμά σας συνεχίζει να παράγει τα αναμενόμενα αποτελέσματα;\n\n**1.2 Περισσότερες πράξεις (Προχωρημένο, Προαιρετικό)**\n\nΤροποποιήστε το calc πρόγραμμά σας προκειμένου να πραγματοποιεί πρόσθεση Ή αφαίρεση\nανάλογα με το τι προτιμάει ο χρήστης. Πώς θα σχεδιάζατε την εφαρμογή σας;\n\n**1.3 Χειρισμός σφαλμάτων (Προχωρημένο, Προαιρετικό)**\n\nΤροποποιήστε το calc πρόγραμμα προκειμένου να βγάζει κωδικό εξόδου 1 εάν οτιδήποτε πάει\nστραβά κατά την εκτέλεση του προγράμματος - για παράδειγμα εάν ο χρήστης δώσει το string\n\"hello\" αντί για αριθμό.",
  "hint": "Δύο κλήσεις της `scanf`, μία για κάθε αριθμό, με τη διεύθυνση της μεταβλητής ως όρισμα.\nΓια το 1.1, ένας `int` σταματά γύρω στο $2 \\cdot 10^9$: χρειάζεστε ευρύτερο τύπο και την\nαντίστοιχη προδιαγραφή σε `scanf`/`printf` (και σκεφτείτε αν χωράει το άθροισμα δύο\nτέτοιων αριθμών). Για το 1.3, ελέγξτε την τιμή που επιστρέφει η `scanf` και τι\nεπιστρέφει η `main`."
 },
 {
  "id": "lab-lab02-pyth",
  "kind": "lab",
  "title": "Πυθαγόρειο θεώρημα",
  "source": {
   "title": "Εργαστήριο 2, Άσκηση 2",
   "url": "https://progintro.github.io/lab-material/labs/lab02/",
   "years": [
    2025
   ]
  },
  "chapters": [
   3,
   5,
   9
  ],
  "topics": [
   "floating-point",
   "operators",
   "input-output"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α3.7",
  "path": "questions/labs/lab-lab02-pyth.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab02-pyth.html",
  "statement": "Γράψτε ένα πρόγραμμα `pyth.c` που δέχεται 2 inputs - τα μήκη των καθέτων πλευρών ενός\nορθογωνίου τριγώνου και τυπώνει τα ακόλουθα:\n\n1. Το εμβαδόν του τριγώνου.\n2. Την περίμετρο του τριγώνου.",
  "hint": "Η υποτείνουσα προκύπτει από το πυθαγόρειο θεώρημα, οπότε θα χρειαστείτε τετραγωνική ρίζα\nαπό τη `math.h` (και `-lm` στη μεταγλώττιση). Διαβάστε τα μήκη ως αριθμούς κινητής\nυποδιαστολής και προσέξτε την ακέραια διαίρεση στο μισό του γινομένου των καθέτων."
 },
 {
  "id": "lab-lab02-readint",
  "kind": "lab",
  "title": "Διάβασμα ακεραίου με scanf",
  "source": {
   "title": "Εργαστήριο 2, Βήμα 3",
   "url": "https://progintro.github.io/lab-material/labs/lab02/",
   "years": [
    2025
   ]
  },
  "chapters": [
   9,
   2
  ],
  "topics": [
   "input-output",
   "input-validation",
   "variables"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α9.12",
  "path": "questions/labs/lab-lab02-readint.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab02-readint.html",
  "statement": "Δημιουργήστε ένα αρχείο `readint.c` με τα ακόλουθα περιεχόμενα:\n\n```c\n/* File: readint.c */\n\n#include <stdio.h>\n\nint main() {\n  int number;\n\n  printf(\"Please give me a number: \");\n  scanf(\"%d\", &number);\n\n  printf(\"I just read this number: %d\\n\", number);\n  return 0;\n}\n```\n\nΜεταγλωττίστε και τρέξτε το παραπάνω πρόγραμμα. Πώς συμπεριφέρεται;\n\nΤι συμβαίνει αν αντί για αριθμό δώσετε μια λέξη ή μια κενή γραμμή;\n\nΤι συμβαίνει αν αντί για αριθμό πληκτρολογήσουμε `Ctrl+D` (EOF);\n\nΤι θα συμβεί αν τυπώσουμε την μεταβλητή `number` πριν τη διαβάσουμε;\n\nΓιατί να μην δώσουμε μια σταθερή τιμή στην μεταβλητή `number` στο πρόγραμμά μας - γιατί\nνα ζητήσουμε από τον χρήστη να δώσει μια τιμή;\n\nΑν χρειαζόταν να διαβάσετε έναν αριθμό κινητής υποδιαστολής, πώς θα το κάνατε;",
  "hint": "Η `scanf` επιστρέφει πόσες τιμές διάβασε επιτυχώς: δεν αλλάζει τη μεταβλητή όταν\nαποτυγχάνει. Αναρωτηθείτε λοιπόν ποια τιμή έχει μια τοπική μεταβλητή που δεν\nαρχικοποιήθηκε ποτέ, και πώς η `scanf` χειρίζεται τα κενά και τις αλλαγές γραμμής\nπριν από έναν αριθμό."
 },
 {
  "id": "lab-lab03-birthdate",
  "kind": "lab",
  "title": "Υπολογισμός ημέρας μίας δεδομένης ημερομηνίας",
  "source": {
   "title": "Εργαστήριο 3, Άσκηση 3",
   "url": "https://progintro.github.io/lab-material/labs/lab03/",
   "years": [
    2025
   ]
  },
  "chapters": [
   5,
   6
  ],
  "topics": [
   "operators",
   "conditionals"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α5.8",
  "path": "questions/labs/lab-lab03-birthdate.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab03-birthdate.html",
  "statement": "Ο ακόλουθος αλγόριθμος υπολογίζει την ημέρα που αντιστοιχεί σε μία δεδομένη ημερομηνία:\n\nΈστω η ημερομηνία $DD / MM / YYYY$ (δύο ψηφία για την μέρα DD - Day, δύο ψηφία για τον\nμήνα MM - Month, 4 ψηφία για τον χρόνο YYYY - Year).\n\n**Αν** $\\text{MM} \\leq 2$, **τότε**:\n\n$$\\begin{matrix} \\text{NYYYY} = \\text{YYYY} - 1 \\\\ \\text{NMM} = 0 \\\\ \\end{matrix}$$\n\n**Αν** $\\text{MM} > 2$, **τότε**:\n\n$$\\begin{matrix} \\text{NYYYY} = \\text{YYYY} \\\\ \\text{NMM} = \\left\\lfloor \\frac{4 \\cdot \\text{MM} + 23}{10} \\right\\rfloor \\\\ \\end{matrix}$$\n\n$$IDAY = 365 \\cdot YYYY + DD + 31 \\cdot (MM - 1) - NMM + \\left\\lfloor \\frac{NYYYY}{4}\\right\\rfloor - \\left\\lfloor \\frac{3}{4} \\cdot \\left(\\left\\lfloor \\frac{NYYYY}{100} \\right\\rfloor + 1\\right) \\right\\rfloor$$\n\nΓια τον υπολογισμό της ημέρας, αν:\n\n- $IDAY \\mod 7 = 0$, τότε DAY = **Saturday**\n- $IDAY \\mod 7 = 1$, τότε DAY = **Sunday**\n- ...\n- $IDAY \\mod 7 = 6$, τότε DAY = **Friday**\n\nΌπου, με $\\lfloor x \\rfloor$ συμβολίζουμε τον μέγιστο ακέραιο αριθμό που δεν είναι\nμεγαλύτερος του αριθμού $x$ - γνωστή και ως συνάρτηση `floor`\n([αντίστοιχα υπάρχει και η συνάρτηση ceil](https://en.wikipedia.org/wiki/Floor_and_ceiling_functions)).\nΔεν είμαστε σίγουροι πώς λειτουργεί - πώς θα το βρούμε;\n\n**Εργασία**: Γράψτε ένα πρόγραμμα `birthdate.c` το οποίο να χρησιμοποιεί τον αλγόριθμο\nπαραπάνω και να υπολογίζει τι ημέρα γεννηθήκατε (ενσωματώστε την ημερομηνία γέννησής σας\nμέσα στο πρόγραμμα).\n\nΟ παραπάνω υπολογισμός φαίνεται περίπλοκος; Δεν έχετε δει τίποτε ακόμη! Πραγματικές\nσυναρτήσεις βιβλιοθήκης ημερομηνιών πρέπει να χειρίζονται ημερομηνίες και στο παρελθόν,\nμε ιδιαίτερα περίπλοκες αλλαγές - τι γίνεται για παράδειγμα αν ο χρήστης θέλει να βρει\nτην ημερομηνία 16 Φεβρουαρίου 1923 στην Ελλάδα\n[[8]](https://en.wikipedia.org/wiki/Adoption_of_the_Gregorian_calendar);",
  "hint": "Για θετικούς αριθμούς, η ακέραια διαίρεση της C κάνει ήδη το $\\lfloor \\cdot \\rfloor$,\nοπότε δεν χρειάζεστε `floor`. Προσέξτε τον όρο $\\frac{3}{4} \\cdot (\\dots)$: αν τον γράψετε\nαφελώς σε ακέραια αριθμητική, το `3/4` βγαίνει 0, άρα αλλάξτε τη σειρά των πράξεων\n(πρώτα πολλαπλασιασμός, μετά διαίρεση). Για την ονομασία της ημέρας αρκεί μια αλυσίδα\n`if`/`else if` ή ένα `switch` πάνω στο υπόλοιπο."
 },
 {
  "id": "lab-lab03-limit",
  "kind": "lab",
  "title": "Αποσφαλμάτωση αθροίσματος με όριο",
  "source": {
   "title": "Εργαστήριο 3, Άσκηση 4",
   "url": "https://progintro.github.io/lab-material/labs/lab03/",
   "years": [
    2025
   ]
  },
  "chapters": [
   6
  ],
  "topics": [
   "loops",
   "debugging",
   "floating-point"
  ],
  "difficulty": 1,
  "type": "debug",
  "label": "Α6.10",
  "path": "questions/labs/lab-lab03-limit.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab03-limit.html",
  "statement": "Το παρακάτω πρόγραμμα `limit.c` ευελπιστεί να υπολογίζει την παράσταση\n1 - 1/2 + 1/4 - 1/8 + 1/16 - ... για όσους όρους είναι μεγαλύτεροι από το `LIMIT`. Για\nνα το πετύχει αυτό, ο προγραμματιστής του έκανε την εξής σκέψη:\n\n> \"Σε μια μεταβλητή `c` θα κρατάω τον τρέχοντα όρο που θα προστεθεί, ο οποίος παράγεται\n> από τον προηγούμενο αν πολλαπλασιάσω με ½. Θέλω ανά πάσα στιγμή ο όρος `c` να μην\n> ξεπερνά το `LIMIT`. Το `c` έχει διαφορετικό πρόσημο σε κάθε όρο, οπότε θα χρησιμοποιήσω\n> μια μεταβλητή `sign` που θα την πολλαπλασιάζω με το -1 ώστε ανά δύο όρους να έχει το\n> ίδιο πρόσημο. Τελικά θα εκτυπώσω το άθροισμα `S`\".\n\nΤο πρόγραμμα αυτό όμως έχει λογικά λάθη. Μπορείτε να το αποσφαλματώσετε και να γράψετε\nένα σωστό `limit.c`;\n\n```c\n#include <stdio.h>\n\n#define LIMIT 0.008\n\nint main() {\n    float S = 0, c = 1;\n    int sign = 1;\n\n    while (c < LIMIT) {\n        S = S + c;\n        sign = (-1) * sign;\n        c = sign * (1.0 / 2) * c;\n    }\n\n    printf(\"%f\\n\", S);\n}\n```",
  "hint": "Βάλτε μια `printf` μέσα στον βρόχο που τυπώνει `S`, `c` και `sign` σε κάθε επανάληψη και\nδείτε πόσες φορές εκτελείται. Ελέγξτε τη συνθήκη σε σχέση με το τι σημαίνει «όροι\nμεγαλύτεροι από το `LIMIT`», και αναρωτηθείτε τι γίνεται στη σύγκριση όταν ο όρος\nγίνει αρνητικός. Επίσης, αφού το `c` κουβαλά ήδη το πρόσημο του προηγούμενου όρου, τι\nκάνει ο πολλαπλασιασμός με το `sign` που αλλάζει κάθε φορά;"
 },
 {
  "id": "lab-lab03-root",
  "kind": "lab",
  "title": "Υπολογισμός ριζών τριωνύμου",
  "source": {
   "title": "Εργαστήριο 3, Άσκηση 2",
   "url": "https://progintro.github.io/lab-material/labs/lab03/",
   "years": [
    2025
   ]
  },
  "chapters": [
   6,
   5
  ],
  "topics": [
   "conditionals",
   "floating-point",
   "math-algorithms"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α6.12",
  "path": "questions/labs/lab-lab03-root.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab03-root.html",
  "statement": "**2.1 Παραγωγή τυχαίων αριθμών**\n\nΓράψτε ένα πρόγραμμα `root.c` που να παράγει τρεις τυχαίους πραγματικούς αριθμούς στο\nδιάστημα `[0,1]` και να τους αποθηκεύει στις μεταβλητές τύπου `double` `a`, `b` και `c`,\nτις οποίες στη συνέχεια να εκτυπώνει.\n\n> **`int rand()`**\n>\n> Απαιτείται ενσωμάτωση του αρχείου επικεφαλίδας `stdlib.h`.\n>\n> Επιστρέφει έναν ψευδο-τυχαίο ακέραιο από 0 έως `RAND_MAX` - συμβολική σταθερά που\n> ορίζεται στο αρχείο επικεφαλίδας `stdlib.h`.\n\n> **`void srand(unsigned int seed)`**\n>\n> Απαιτείται ενσωμάτωση του αρχείου επικεφαλίδας `stdlib.h`.\n>\n> Αρχικοποιεί την γεννήτρια ψευδο-τυχαίων αριθμών με βάση τον αριθμό/φύτρα `seed`.\n> Συνήθως χρησιμοποιούμε σα φύτρα την τρέχουσα ώρα, όπως επιστρέφεται από την κλήση της\n> συνάρτησης `time(NULL)` (απαιτείται το αρχείο επικεφαλίδας `time.h`).\n\n**2.2 Εύρεση ριζών**\n\nΤροποποιήστε το `root.c` ώστε να υπολογίζει τις πραγματικές ρίζες ενός τριωνύμου. Τα\nδεδομένα εισόδου (συντελεστές του τριωνύμου) θα είναι τυχαίες πραγματικές μεταβλητές\n`a`, `b`, `c` στο διάστημα `[0,1]`. Αν το τριώνυμο δεν έχει πραγματικές ρίζες, να\nεκτυπώνεται ένα σχετικό μήνυμα ενημέρωσης. Οι ρίζες να εκτυπώνονται με ακρίβεια 3\nδεκαδικών ψηφίων.\n\nΘυμηθείτε τη δομή ελέγχου `if...else`:\n\n```c\nif (C)\n    E1;\nelse\n    E2;\n```\n\nΑν η συνθήκη `C` είναι αληθής εκτελείται η εντολή (ή το μπλοκ εντολών) `E1`, αλλιώς η\nεντολή (ή το μπλοκ εντολών) `E2`. Το σκέλος `else` είναι προαιρετικό: αν λείπει και η\n`C` είναι ψευδής, δεν εκτελείται τίποτα.\n\n**2.3 Μιγαδικές ρίζες**\n\nΕνσωματώστε στο πρόγραμμά σας και την περίπτωση το τριώνυμο να έχει μιγαδικές ρίζες,\nοπότε θα πρέπει να τις υπολογίζει.",
  "hint": "Για τυχαίο πραγματικό στο `[0,1]` διαιρέστε το αποτέλεσμα της `rand()` με το `RAND_MAX`,\nπροσέχοντας να γίνει η διαίρεση σε `double`. Οι περιπτώσεις καθορίζονται από το πρόσημο\nτης διακρίνουσας. Για τις μιγαδικές ρίζες τυπώστε χωριστά πραγματικό και φανταστικό\nμέρος, χρησιμοποιώντας την απόλυτη τιμή της διακρίνουσας."
 },
 {
  "id": "lab-lab03-seq",
  "kind": "lab",
  "title": "Υπολογισμός αθροίσματος σειράς",
  "source": {
   "title": "Εργαστήριο 3, Άσκηση 1",
   "url": "https://progintro.github.io/lab-material/labs/lab03/",
   "years": [
    2025
   ]
  },
  "chapters": [
   6,
   3
  ],
  "topics": [
   "loops",
   "functions",
   "floating-point"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α6.13",
  "path": "questions/labs/lab-lab03-seq.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab03-seq.html",
  "statement": "Σε αυτήν την άσκηση, θα γράψουμε ένα πρόγραμμα `seq.c` το οποίο θα υπολογίζει διάφορα\nαθροίσματα σειράς. Για κάθε ένα από αυτά, θα φτιάχνουμε μια διαφορετική συνάρτηση\nυπολογισμού.\n\n**1.1** Γράψτε μια συνάρτηση `sum` που να υπολογίζει το άθροισμα της σειράς:\n\n$$\\sum_{i=1}^{100} i$$\n\nκαι να το εκτυπώνει στην οθόνη. Να χρησιμοποιηθεί η δομή επανάληψης `while`.\n\n**1.2** Γράψτε μια συνάρτηση `basel` που να υπολογίζει το άθροισμα της σειράς:\n\n$$\\sum_{i=1}^{100} \\frac{1}{i^2}$$\n\nκαι να το εκτυπώνει στην οθόνη. Να χρησιμοποιηθεί η δομή επανάληψης `for`.\n\nΤι συμβαίνει αν αυξήσετε τους όρους; Ρίξτε μια ματιά στο\n[Basel Theorem](https://en.wikipedia.org/wiki/Basel_problem) και ελέγξτε αν τα\nαποτελέσματά σας συμφωνούν με τα μαθηματικά.\n\n> Υπόδειξη: Χρησιμοποιήστε μία ενδιάμεση μεταβλητή για να αποθηκεύετε προσωρινά τον\n> τρέχοντα όρο της σειράς.\n\n**1.3** Γράψτε μια συνάρτηση `pi_approx` που να προσεγγίζει το $\\pi$ χρησιμοποιώντας την\nέκφραση:\n\n$$\\pi = \\sqrt{6 \\cdot \\sum_{i=1}^\\infty \\frac{1}{i^2}}$$\n\nχρησιμοποιώντας τους 100 πρώτους όρους της σειράς και να τυπώνει το αποτέλεσμα. Να\nχρησιμοποιηθεί η δομή επανάληψης `do...while`. Για την υλοποίηση θα χρειαστείτε την\nσυνάρτηση `sqrt` (square root).\n\n> **`double sqrt(double)`**\n>\n> Απαιτείται η ενσωμάτωση του αρχείου επικεφαλίδας `math.h`.\n>\n> Επιστρέφει την τετραγωνική ρίζα του αριθμού που δέχεται σαν όρισμα.\n>\n> Στην μεταγλώττιση με τον `gcc` απαιτείται και η επιλογή `-lm` για να συμπεριληφθεί η\n> μαθηματική βιβλιοθήκη.\n\n**1.3.1** Τροποποίηση της `pi_approx` μέχρι όριο ακρίβειας $10^{-15}$.\n\nΠαρατηρήστε ότι οι όροι που προστίθενται στην σειρά γίνονται ολοένα και πιο μικροί, με\nαποτέλεσμα από ένα σημείο και μετά να είναι αρκούντως μικροί για να μην επηρεάζουν το\nαποτέλεσμα, αφού χρησιμοποιούμε αριθμητική πεπερασμένης ακρίβειας. Αλλάξτε το κριτήριο\nτερματισμού του υπολογισμού, ώστε ο υπολογισμός να σταματάει όταν ο τρέχων όρος που\nπροστίθεται στην σειρά είναι μικρότερος από $10^{-15}$.\n\n**1.3.2** Τροποποίηση της `pi_approx` ώστε να τυπώνει το αποτέλεσμα με ακρίβεια 8\nδεκαδικών ψηφίων.\n\nΗ συνάρτηση `printf()` μπορεί να εκτυπώσει την τιμή πραγματικών μεταβλητών που δέχεται\nσαν όρισμα με επιθυμητή μορφοποίηση. Σύνταξη:\n\n```c\nprintf(\"%a.bf\", var);\n```\n\nόπου:\n\n- `a`: Ορίζουμε το πλήθος των θέσεων που θα γίνει η εκτύπωση.\n- `b`: Ορίζουμε το πλήθος των ψηφίων μετά την υποδιαστολή που θα εκτυπωθούν.\n\nΜέχρι πόσα ψηφία του $\\pi$ μπορείτε να υπολογίσετε / τυπώσετε; Αυτό το πρόβλημα έχει\nτυραννήσει γενιές και γενιές στα μαθηματικά και αργότερα - όταν οι αριθμοί έγιναν\nμεγάλοι - στην πληροφορική\n[[1]](https://en.wikipedia.org/wiki/Chronology_of_computation_of_%CF%80)\n[[2]](https://en.wikipedia.org/wiki/Approximations_of_%CF%80).\n\n**1.4** Υλοποιήστε μια συνάρτηση `eta_two` η οποία να υπολογίζει το άθροισμα της σειράς:\n\n$$S_{1} = \\frac{1}{1^{2}} - \\frac{1}{2^{2}} + \\frac{1}{3^{2}} - \\frac{1}{4^{2}} + \\frac{1}{5^{2}} - \\frac{1}{6^{2}} + \\dots$$\n\nή αλλιώς γραμμένη ως:\n\n$$S_{1} = \\sum_{i=1}^\\infty \\frac{(-1)^{i-1}}{i^2}$$\n\nΗ συνάρτησή σας θέλουμε να ζητάει από τον χρήστη το πλήθος των όρων που θα χρησιμοποιήσει\nκαι να τυπώνει το αποτέλεσμα με ακρίβεια 6 δεκαδικών ψηφίων. Μπορείτε να χρησιμοποιήσετε\nόποια δομή επανάληψης επιθυμείτε.\n\nΦαίνεται το αποτέλεσμά σας να συγκλίνει σε κάποιον αριθμό; Μπορείτε να το εξηγήσετε με\nτην βοήθεια της συνάρτησης\n[Dirichlet eta](https://en.wikipedia.org/wiki/Dirichlet_eta_function);\n\n**1.5 Εξάσκηση σε σειρές**\n\nΜπορείτε να κάνετε περισσότερη εξάσκηση, υλοποιώντας τις ακόλουθες συναρτήσεις στο\nπρόγραμμα `seq.c`:\n\n- Συνάρτηση `harmonic`\n  [[3]](https://en.wikipedia.org/wiki/Harmonic_series_(mathematics)#Alternating_harmonic_series)\n  που υπολογίζει το άθροισμα της εναλλάσσουσας αρμονικής σειράς:\n\n$$S_{2} = \\sum_{i=1}^\\infty \\frac{(-1)^{i+1}}{i} = \\frac{1}{1} - \\frac{1}{2} + \\frac{1}{3} - \\frac{1}{4} + \\cdots$$\n\n- Συνάρτηση `leibniz` [[4]](https://en.wikipedia.org/wiki/Leibniz_formula_for_%CF%80)\n  που να υπολογίζει το άθροισμα:\n\n$$S_{3} = \\sum_{i=0}^\\infty \\frac{(-1)^{i}}{2i+1} = \\frac{1}{1} - \\frac{1}{3} + \\frac{1}{5} - \\frac{1}{7} + \\cdots$$\n\n- Συνάρτηση `zeta_four` [[5]](https://en.wikipedia.org/wiki/Riemann_zeta_function) που\n  να υπολογίζει το άθροισμα:\n\n$$S_{4} = \\sum_{i=1}^\\infty \\frac{1}{i^4} = \\frac{1}{1^4} + \\frac{1}{2^4} + \\frac{1}{3^4} + \\frac{1}{4^4} + \\cdots$$\n\n- Συνάρτηση `wallis` [[6]](https://en.wikipedia.org/wiki/Wallis_product) που να\n  υπολογίζει το γινόμενο:\n\n$$P = \\prod_{i=1}^\\infty \\frac{2i}{2i-1}\\cdot \\frac{2i}{2i+1} = \\frac{2}{1} \\cdot \\frac{2}{3} \\cdot \\frac{4}{3} \\cdot \\frac{4}{5} \\cdot \\frac{6}{5} \\cdot \\frac{6}{7} \\cdots$$\n\n- Συνάρτηση `ramanujan` [[7]](https://en.wikipedia.org/wiki/Ramanujan%E2%80%93Sato_series)\n  που να υπολογίζει το π χρησιμοποιώντας την σχέση:\n\n$$\\frac{1}{\\pi} = \\frac{2\\sqrt{2}}{9801} \\sum_{k=0}^{\\infty} \\frac{(4k)! \\cdot (1103 + 26390k)}{(k!)^4 \\cdot 396^{4k}}$$",
  "hint": "Κάθε σειρά είναι ένας βρόχος με έναν συσσωρευτή (αρχικοποιημένο σε 0 για άθροισμα, σε 1\nγια γινόμενο) και έναν τρέχοντα όρο. Προσοχή στην ακέραια διαίρεση: το `1/(i*i)` με\nακέραιο `i` κάνει 0, οπότε ο υπολογισμός πρέπει να γίνεται σε `double`. Για τις\nεναλλασσόμενες σειρές κρατήστε ένα πρόσημο που αλλάζει σε κάθε βήμα αντί να καλείτε\n`pow`, και για το 1.3.1 ο έλεγχος τερματισμού συγκρίνει τον τρέχοντα όρο με το όριο."
 },
 {
  "id": "lab-lab04-encode-decode",
  "kind": "lab",
  "title": "Κωδικοποίηση και αποκωδικοποίηση κειμένου",
  "source": {
   "title": "Εργαστήριο 4, Άσκηση 4",
   "url": "https://progintro.github.io/lab-material/labs/lab04/",
   "years": [
    2025
   ]
  },
  "chapters": [
   9,
   2,
   1
  ],
  "topics": [
   "input-output",
   "redirection",
   "integer-representation"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α9.14",
  "path": "questions/labs/lab-lab04-encode-decode.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab04-encode-decode.html",
  "statement": "Σε αυτήν την άσκηση θα γράψουμε προγράμματα για την δεκαεξαδική κωδικοποίηση και\nαποκωδικοποίηση ενός κειμένου.\n\n**4.1** Δημιουργήστε ένα αρχείο κειμένου με όνομα `text` και πληκτρολογήστε σε αυτό ένα\nτυχαίο κείμενο.\n\n**4.2** Γράψτε ένα πρόγραμμα `encode.c` που να διαβάζει από την είσοδο χαρακτήρες και,\nγια καθένα απ' αυτούς, να εκτυπώνει στην έξοδο τον ASCII κωδικό που έχει σε δεκαεξαδική\nμορφή χρησιμοποιώντας ακριβώς δύο ψηφία. Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ echo hello world | ./encode\n68656c6c6f20776f726c640a\n```\n\n**4.3** Εκτελέστε το πρόγραμμα encode με ανακατεύθυνση εισόδου από το αρχείο `text`.\n\n**4.4** Εκτελέστε το πρόγραμμα encode με ανακατεύθυνση εισόδου από το αρχείο `text` και\nανακατεύθυνση εξόδου στο αρχείο `encoded_text`.\n\n**4.5** Γράψτε ένα πρόγραμμα `decode.c` που να διαβάζει από την είσοδο τα δεκαεξαδικά\nψηφία για τον κάθε χαρακτήρα και για κάθε δύο από αυτά τα ψηφία να εκτυπώνει τον\nχαρακτήρα που αντιστοιχεί σε αυτόν τον δεκαεξαδικό αριθμό. Παράδειγμα εκτέλεσης\nακολουθεί:\n\n```text\n$ echo 68656c6c6f20776f726c640a | ./decode\nhello world\n```\n\nΟ αριθμός `68` αντιστοιχεί στον χαρακτήρα `'h'` κ.ο.κ. Για την αποκωδικοποίηση\nσυνιστούμε να χρησιμοποιήσετε την συνάρτηση `getchar()`. Αν το επιθυμείτε μπορείτε να\nδοκιμάσετε και άλλες λύσεις όπως π.χ., την `scanf(\"%2x\", ...)` αλλά μην ξεχάσετε να\nαποθηκεύσετε το αποτέλεσμα σε μεταβλητή τύπου `int` (και να μεταγλωττίσετε με το flag\n`-Wall` αλλιώς είναι πιθανό να σας ξεφύγουν διάφορα λαθάκια).\n\n**4.6** Μεταγλωττίστε το και εκτελέστε το με ανακατεύθυνση της εισόδου από το αρχείο\n`encoded_text`.\n\n**4.7** Εκτελέστε το πρόγραμμα `decode` για την αποκωδικοποίηση ενός κωδικοποιημένου\nκειμένου, έτσι ώστε να παίρνει την είσοδό του απ' ευθείας από το πρόγραμμα `encode`, το\nοποίο να καλείται έτσι ώστε να κωδικοποιεί το αρχείο `text`, χωρίς να χρησιμοποιήσετε το\nενδιάμεσο αρχείο `encoded_text`. Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ echo hello world | ./encode | ./decode\nhello world\n```",
  "hint": "Για το `encode`, η `printf` με πλάτος πεδίου και μηδενικά μπροστά δίνει πάντα δύο\nδεκαεξαδικά ψηφία. Για το `decode` με `getchar`, διαβάστε τα ψηφία ανά ζεύγη, μετατρέψτε\nκάθε ψηφίο (`0`–`9` ή `a`–`f`) στην τιμή του 0–15 και συνδυάστε τα\nως $16 \\cdot \\text{πρώτο} + \\text{δεύτερο}$. Σκεφτείτε τι κάνετε με την τελική αλλαγή γραμμής της\nεισόδου, που δεν είναι δεκαεξαδικό ψηφίο."
 },
 {
  "id": "lab-lab04-lowercase",
  "kind": "lab",
  "title": "Τροποποίηση κειμένου",
  "source": {
   "title": "Εργαστήριο 4, Άσκηση 3",
   "url": "https://progintro.github.io/lab-material/labs/lab04/",
   "years": [
    2025
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output",
   "redirection",
   "conditionals"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α9.13",
  "path": "questions/labs/lab-lab04-lowercase.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab04-lowercase.html",
  "statement": "**3.1** Αντιγράψτε το αρχείο `capitalize.c` παρακάτω, μεταγλωττίστε το και εκτελέστε το\nμε είσοδο το ίδιο το πηγαίο αρχείο `capitalize.c`. Παρατηρήστε τη λειτουργία του.\n\n```c\n/* File: capitalize.c */\n\n#include <stdio.h>\n\nint main() {\n  int ch; /* Be careful! Declare ch as int because of getchar() and EOF */\n  ch = getchar(); /* Read first character */\n  while (ch != EOF) { /* Go on if we didn't reach end of file */\n    if (ch >= 'a' && ch <= 'z') { /* If lower case letter */\n      ch = ch - ('a'-'A'); /* Move 'a'-'A' positions in the ASCII table */\n    }\n    putchar(ch); /* Print out character */\n    ch = getchar(); /* Read next character */\n  }\n  return 0;\n}\n```\n\nΗ συνάρτηση `getchar()` διαβάζει έναν χαρακτήρα από την είσοδο και επιστρέφει τον ASCII\nκωδικό του χαρακτήρα. Αν δεν υπάρχει άλλος χαρακτήρας για διάβασμα στην είσοδο,\nεπιστρέφει την ειδική ακέραια τιμή EOF που είναι ορισμένη στο stdio.h.\n\n**3.2** Γράψτε ένα πρόγραμμα `lowercase.c`, ώστε να κάνει το αντίστροφο, δηλαδή να\nμετατρέπει τους χαρακτήρες που εμφανίζονται με κεφαλαία γράμματα σε χαρακτήρες με μικρά\nγράμματα.\n\n**3.3** Τροποποιήστε το `lowercase.c`, ώστε να μετατρέπονται ταυτόχρονα και οι κεφαλαίοι\nχαρακτήρες σε μικρούς και οι μικροί σε κεφαλαίους.",
  "hint": "Κρατήστε τον ίδιο σκελετό ανάγνωσης μέχρι το `EOF` και αλλάξτε μόνο τον έλεγχο και τη\nμετατόπιση στον πίνακα ASCII. Στο 3.3 προσέξτε να μη μετατρέψετε έναν χαρακτήρα δύο\nφορές: οι δύο περιπτώσεις πρέπει να αποκλείουν η μία την άλλη."
 },
 {
  "id": "lab-lab04-printchar",
  "kind": "lab",
  "title": "Εκτύπωση χαρακτήρων",
  "source": {
   "title": "Εργαστήριο 4, Άσκηση 1",
   "url": "https://progintro.github.io/lab-material/labs/lab04/",
   "years": [
    2025
   ]
  },
  "chapters": [
   2,
   6
  ],
  "topics": [
   "types",
   "input-output",
   "loops"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α2.11",
  "path": "questions/labs/lab-lab04-printchar.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab04-printchar.html",
  "statement": "Γράψτε ένα πρόγραμμα `printchar.c` που να εκτυπώνει τους χαρακτήρες με ASCII κωδικό που\nείναι πολλαπλάσιο του 3, και μεταξύ 33 και 105, μαζί με τους κωδικούς τους σε δεκαδική\nκαι δεκαεξαδική μορφή. Το πρόγραμμά σας θέλουμε να τυπώνει σε κάθε γραμμή έναν χαρακτήρα,\nακολουθούμενο από τον δεκαδικό και τον δεκαεξαδικό κωδικό του. Παράδειγμα εκτέλεσης\nακολουθεί:\n\n```text\n$ ./printchar\n! - (dec: 33, hex: 21)\n$ - (dec: 36, hex: 24)\n' - (dec: 39, hex: 27)\n* - (dec: 42, hex: 2a)\n- - (dec: 45, hex: 2d)\n0 - (dec: 48, hex: 30)\n3 - (dec: 51, hex: 33)\n...\n```\n\nΠαρατηρήστε την έξοδο του προγράμματος σε σχέση με τον πίνακα των ASCII κωδικών (δείτε\nτον πλήρη πίνακα στο\n[εργαστήριο](https://progintro.github.io/lab-material/labs/lab04/) ή με την εντολή\n`man ascii`).",
  "hint": "Ένας χαρακτήρας στη C είναι απλώς ένας μικρός ακέραιος: η ίδια τιμή τυπώνεται ως\nχαρακτήρας, ως δεκαδικός ή ως δεκαεξαδικός ανάλογα με την προδιαγραφή της `printf`\n(`%c`, `%d`, `%x`). Ο βρόχος μπορεί να ξεκινά από το πρώτο πολλαπλάσιο του 3 στο διάστημα\nκαι να προχωρά με βήμα 3."
 },
 {
  "id": "lab-lab04-pyramid",
  "kind": "lab",
  "title": "Κατασκευή πυραμίδας",
  "source": {
   "title": "Εργαστήριο 4, Άσκηση 2",
   "url": "https://progintro.github.io/lab-material/labs/lab04/",
   "years": [
    2025
   ]
  },
  "chapters": [
   6,
   9
  ],
  "topics": [
   "loops",
   "input-output"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α6.11",
  "path": "questions/labs/lab-lab04-pyramid.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab04-pyramid.html",
  "statement": "**2.1** Γράψτε ένα πρόγραμμα `pyramid.c` που να εκτυπώνει στην οθόνη σχήμα με την\nακόλουθη μορφή χρησιμοποιώντας αποκλειστικά την συνάρτηση `putchar`:\n\n```text\n*\n**\n***\n****\n*****\n******\n```\n\nΤο πλήθος των γραμμών που θα εκτυπωθούν να το διαβάζετε με χρήση `scanf`.\n\n> **`int putchar(int c)`**\n>\n> Η συνάρτηση `putchar(int c)` εκτυπώνει τον χαρακτήρα που αντιστοιχεί στον ASCII\n> κωδικό που δέχεται σαν όρισμα.\n>\n> Ισοδύναμες χρήσεις: `putchar('*')` ή `putchar(42)`, όπου 42 είναι ο ASCII κωδικός του\n> χαρακτήρα `*`.\n\n**2.2** Τροποποιήστε το `pyramid.c` ώστε να εκτυπώνει στην οθόνη σχήμα με την ακόλουθη\nμορφή:\n\n```text\n*\n***\n*****\n*******\n*********\n***********\n```\n\nExtra: τροποποιήστε το `pyramid.c` ώστε το βήμα με το οποίο αυξάνεται ο αριθμός των `*`\nανά γραμμή να καθορίζεται επίσης από τον χρήστη με χρήση `scanf`.",
  "hint": "Δύο εμφωλευμένοι βρόχοι: ο εξωτερικός μετράει γραμμές και ο εσωτερικός τυπώνει τα\nαστεράκια της τρέχουσας γραμμής, και μετά τον εσωτερικό τυπώνετε την αλλαγή γραμμής.\nΒρείτε έναν τύπο για το πλήθος των `*` στη γραμμή $i$ (για το 2.2 και για το γενικό\nβήμα)."
 },
 {
  "id": "lab-lab05-collatz",
  "kind": "lab",
  "title": "Η εικασία του Collatz",
  "source": {
   "title": "Εργαστήριο 5, Άσκηση 1",
   "url": "https://progintro.github.io/lab-material/labs/lab05/",
   "years": [
    2025
   ]
  },
  "chapters": [
   11,
   3
  ],
  "topics": [
   "recursion",
   "functions",
   "integer-representation"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α11.15",
  "path": "questions/labs/lab-lab05-collatz.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab05-collatz.html",
  "statement": "Η εικασία Collatz είναι ένα από τα πιο\n[διάσημα άλυτα προβλήματα των μαθηματικών](https://en.wikipedia.org/wiki/Collatz_conjecture).\nΠολλοί μαθηματικοί έχουν επιχειρήσει κατά καιρούς να την αποδείξουν και μέχρι στιγμής δεν\nέχουμε ακόμα μια ευρέως αποδεκτή απόδειξη. Η εικασία ισχυρίζεται κάτι πολύ απλό: ότι η\nεπανάληψη δυο απλών αριθμητικών πράξεων με μια συγκεκριμένη διαδικασία μπορεί να\nμετατρέψει οποιονδήποτε θετικό ακέραιο στο 1. Η διαδικασία των πράξεων έχει ως εξής:\n\n1. Διάλεξε οποιονδήποτε θετικό ακέραιο $N$.\n2. Αν ο αριθμός είναι 1, τότε τερμάτισε την διαδικασία.\n3. Αν είναι άρτιος, ο επόμενος αριθμός στην ακολουθία θα είναι ο $N/2$.\n4. Αν είναι περιττός, ο επόμενος αριθμός στην ακολουθία θα είναι ο $3\\times N+1$.\n5. Επανάλαβε τα βήματα 2-4 μέχρι να φτάσουμε στο 1.\n\nΓια παράδειγμα, έστω $N = 3$. Η παραπάνω διαδικασία θα παράξει την ακολουθία: 3, 10, 5,\n16, 8, 4, 2, 1. Μπορείτε να δοκιμάσετε το ίδιο με τον αγαπημένο σας θετικό ακέραιο και να\nελέγξετε την ακολουθία που παράγεται. Ας πάρουμε για παράδειγμα το 42, που οδηγεί στην\nακολουθία: 42, 21, 64, 32, 16, 8, 4, 2, 1. Λογικά και η δική σας επιλογή κατέληξε στο 1\nμετά από μερικά βήματα - αν όχι ίσως έχετε την\n[ευκαιρία να γίνετε εκατομμυριούχοι](https://www.prnewswire.com/news-releases/bakuage-offers-prize-of-120-million-jpy-to-whoever-solves-collatz-conjecture-math-problem-unsolved-for-84-years-301326629.html)\n(ποιος είπε ότι τα μαθηματικά δεν έχουν λεφτά!).\n\nΓια κάθε θετικό ακέραιο $N$, ο αριθμός στοιχείων της ακολουθίας που παράγεται μέχρι να\nκαταλήξουμε στο 1, λέγεται *μήκος ακολουθίας Collatz*. Για παράδειγμα, για $N = 3$, το\nμήκος της ακολουθίας είναι 8 (η ακολουθία έχει 8 στοιχεία: 3, 10, 5, 16, 8, 4, 2, 1).\nΑντίστοιχα για τον αριθμό 42, το μήκος ακολουθίας Collatz είναι 9. Αν $N = 1$, τότε έχουμε\nτο ελάχιστο μήκος 1.\n\nΣε αυτήν την άσκηση, καλείστε να γράψετε ένα πρόγραμμα `collatz.c` που να βρίσκει το μήκος\nτης ακολουθίας collatz για έναν αριθμό.\n\n**1.1** Κατασκευάστε τη συνάρτηση `int isodd(int n)` που δέχεται σαν όρισμα έναν ακέραιο\n`n` και επιστρέφει 1, αν ο αριθμός είναι περιττός, ή 0, αν ο αριθμός είναι άρτιος.\n\n**1.2** Γράψτε σε γλώσσα C μια συνάρτηση `int collatz_it(int n)` που υπολογίζει το μήκος\nακολουθίας collatz - δηλαδή το πλήθος των αριθμών της ακολουθίας που ξεκινά από τον `n`\nκαι καταλήγει στο 1 (συμπεριλαμβανομένων και των δύο). Ολοκληρώστε την υλοποίηση με δομή\nεπανάληψης.\n\n> **Ορισμός συνάρτησης**\n>\n> ```c\n> <τύπος επιστροφής> <όνομα συνάρτησης>(<τυπικές παράμετροι>)\n> {\n>     <εντολές και δηλώσεις>\n> }\n> ```\n>\n> Ο **τύπος επιστροφής** είναι ο τύπος της τιμής που επιστρέφει η συνάρτηση μέσω της\n> εντολής `return <παράσταση>;`. Αν η συνάρτηση δεν επιστρέφει τιμή, ο τύπος επιστροφής\n> της ορίζεται ως `void`.\n>\n> Οι **τυπικές παράμετροι** είναι οι μεταβλητές - μαζί με τους τύπους τους - που\n> χρησιμοποιεί η συνάρτηση και παίρνουν τιμές από την καλούσα συνάρτηση. Γράφονται\n> χωρισμένες με κόμμα.\n\nΑν μια συνάρτηση καλείται πριν οριστεί, πρέπει να έχει προηγηθεί η προαναγγελία του\n**πρωτοτύπου** της - ο ορισμός της χωρίς σώμα, με ερωτηματικό στο τέλος:\n\n```c\nint collatz_it(int n);   /* πρωτότυπο: προαναγγέλλει τη συνάρτηση */\n\nint main(void)\n{\n    /* εδώ μπορούμε πλέον να καλέσουμε την collatz_it */\n}\n\nint collatz_it(int n)    /* ο ορισμός της συνάρτησης */\n{\n    /* ... */\n}\n```\n\n**1.3** Υλοποιήστε τον ίδιο αλγόριθμο σε μια συνάρτηση `int collatz(int n)` κάνοντας χρήση\nαναδρομής και **χωρίς** να χρησιμοποιήσετε άλλη δομή επανάληψης.\n\n**1.4** Ελέγξτε τα αποτελέσματά σας ώστε να βεβαιωθείτε ότι το πρόγραμμά σας λειτουργεί\nσωστά για διάφορες αρχικές τιμές:\n\n```text\n$ ./collatz\nNumber to find the length of the collatz sequence: 42\nIterative result: 9\nRecursive result: 9\n$ ./collatz\nNumber to find the length of the collatz sequence: 950000001\nIterative result: 199\nRecursive result: 199\n```\n\nΚάποιο από τα αποτελέσματά μας δεν συμφωνεί; Τι μπορεί να πηγαίνει στραβά;\n\n**1.5 (Προχωρημένο, Προαιρετικό)** Κάνετε το πρόγραμμά σας να δέχεται τον ακέραιο από την\nγραμμή εντολών, για παράδειγμα:\n\n```text\n$ ./collatz 950000001\nIterative result: 199\nRecursive result: 199\n```",
  "hint": "Για την αναδρομική εκδοχή, διατυπώστε το μήκος για τον `n` μέσω του μήκους για τον\nεπόμενο αριθμό της ακολουθίας, με βάση την περίπτωση $n = 1$. Για το 1.4, υπολογίστε με\nτο χέρι πόσο γίνεται το $3 \\cdot 950000001 + 1$ και συγκρίνετέ το με το μέγιστο `int`:\nτι τύπος χρειάζεται για τους ενδιάμεσους όρους;"
 },
 {
  "id": "lab-lab05-fib",
  "kind": "lab",
  "title": "Η ακολουθία Fibonacci",
  "source": {
   "title": "Εργαστήριο 5, Άσκηση 2",
   "url": "https://progintro.github.io/lab-material/labs/lab05/",
   "years": [
    2025
   ]
  },
  "chapters": [
   11,
   15,
   14
  ],
  "topics": [
   "recursion",
   "complexity",
   "scope"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α11.16",
  "path": "questions/labs/lab-lab05-fib.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab05-fib.html",
  "statement": "Η ακολουθία Fibonacci είναι από τις\n[πιο διάσημες μαθηματικές ακολουθίες](https://en.wikipedia.org/wiki/Fibonacci_sequence).\nΟ αναδρομικός ορισμός της συνάρτησης είναι ιδιαίτερα απλός:\n\n$$fib(n) = \\begin{cases} 0 & \\text{if } n = 0, \\\\ 1 & \\text{if } n = 1, \\\\ fib(n-1) + fib(n-2) & \\text{if } n \\geq 2. \\end{cases}$$\n\nκαι προκύπτει η ακολουθία (συνδέεται και με την\n[χρυσή τομή](https://en.wikipedia.org/wiki/Golden_ratio)):\n\n```text\n0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...\n```\n\nΣε αυτήν την άσκηση θα υλοποιήσετε ένα πρόγραμμα `fib.c` που υπολογίζει τον n-οστό\nαριθμό της ακολουθίας Fibonacci.\n\n**2.1** Ορίστε την αναδρομική συνάρτηση `int fib(int n)` που να υλοποιεί τον υπολογισμό\nτου n-οστού όρου της ακολουθίας Fibonacci.\n\n**2.2** Μετατρέψτε το πρόγραμμά σας έτσι ώστε να δέχεται από τον χρήστη το πόσους\nαριθμούς Fibonacci θέλει να εκτυπωθούν και στην συνέχεια θα καλεί την συνάρτηση `fib`\nγια να εκτυπώσει τον κάθε όρο. Παράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ ./fib\nHow many fibonacci terms would you like: 35\nfib(0) = 0\nfib(1) = 1\nfib(2) = 1\nfib(3) = 2\nfib(4) = 3\nfib(5) = 5\nfib(6) = 8\nfib(7) = 13\nfib(8) = 21\nfib(9) = 34\n...\nfib(31) = 1346269\nfib(32) = 2178309\nfib(33) = 3524578\nfib(34) = 5702887\n```\n\nΤρέξτε το πρόγραμμά σας για περισσότερους όρους, για παράδειγμα 45. Τι παρατηρείτε;\n\n**2.3** Μετρήστε τις αναδρομικές κλήσεις για κάθε εκτέλεση του παραπάνω προγράμματος\nχρησιμοποιώντας μία καθολική (global) μεταβλητή. Εκτυπώστε το πλήθος των αναδρομικών\nκλήσεων μετά από κάθε εκτέλεση.\n\n```mermaid\nflowchart TB\n  main --> fib4\n  fib4 -->|3| main\n  fib4[\"fib(4)\"] --> fib3[\"fib(3)\"]\n  fib3 --> fib21[\"fib(2)\"]\n  fib3 --> fib13[\"fib(1)\"]\n  fib21 --> fib11[\"fib(1)\"]\n  fib21 --> fib01[\"fib(0)\"]\n  fib4 --> fib22[\"fib(2)\"]\n  fib22 --> fib12[\"fib(1)\"]\n  fib22 --> fib02[\"fib(0)\"]\n  fib02 -->|0| fib22\n  fib12 -->|1| fib22\n  fib22 -->|1| fib4\n  fib01 -->|0| fib21\n  fib11 -->|1| fib21\n  fib21 -->|1| fib3\n  fib13 -->|1| fib3\n  fib3 -->|2| fib4\n```\n\n*Σχήμα: το δένδρο αναδρομικών κλήσεων για `fib(4)`, με τις τιμές που επιστρέφει κάθε κλήση.*\n\n**2.4** Παρατηρήστε το δένδρο αναδρομικών κλήσεων του προγράμματος για n=4 και εξηγήστε\nτην αύξηση του χρόνου υπολογισμού του προγράμματος σε σχέση με τον όρο που υπολογίζεται.\n\n**2.5** Ο n-οστός όρος της ακολουθίας Fibonacci μπορεί να υπολογισθεί και επαναληπτικά,\nαν χρησιμοποιήσουμε δύο μεταβλητές για να αποθηκεύουμε σε κάθε βήμα τους δύο\nπροηγούμενους αριθμούς, ώστε προσθέτοντας τους, να υπολογίζουμε τον επόμενο. Γράψτε μια\nσυνάρτηση `int fib_it(int n)` η οποία να υπολογίζει τον n-οστό όρο της ακολουθίας\nFibonacci ακολουθώντας την παραπάνω επαναληπτική διαδικασία. Μετατρέψτε το πρόγραμμά σας\nώστε να χρησιμοποιεί την επαναληπτική διαδικασία και ξανατρέξτε το παραπάνω πείραμα. Τι\nπαρατηρείτε;\n\n**2.6 (Προχωρημένο, Προαιρετικό)** Μπορείτε να υπολογίσετε τον n-οστό όρο Fibonacci\nαναδρομικά με απόδοση κοντά στον επαναληπτικό αλγόριθμο; Αν ναι, υλοποιήστε την λύση σας\nσε μια συνάρτηση `fib_rec_fast` και μετατρέψτε το πρόγραμμά σας ώστε να χρησιμοποιεί την\nσυνάρτηση `fib_rec_fast`.",
  "hint": "Στο δένδρο κλήσεων, πόσες φορές υπολογίζεται το `fib(2)`; Το ίδιο συμβαίνει σε κάθε\nεπίπεδο, γι' αυτό το πλήθος των κλήσεων μεγαλώνει εκθετικά με το `n`. Ο μετρητής της 2.3\nείναι μια μεταβλητή δηλωμένη έξω από κάθε συνάρτηση, που αυξάνεται στην αρχή της `fib`.\nΓια το 2.6, σκεφτείτε μια αναδρομική συνάρτηση που «κουβαλά» τους δύο τελευταίους όρους\nως ορίσματα, ή που θυμάται όσα έχει ήδη υπολογίσει."
 },
 {
  "id": "lab-lab05-ladder",
  "kind": "lab",
  "title": "Σκαλί-σκαλί (Παλιό θέμα, Προαιρετικό)",
  "source": {
   "title": "Εργαστήριο 5, Άσκηση 3",
   "url": "https://progintro.github.io/lab-material/labs/lab05/",
   "years": [
    2025
   ]
  },
  "chapters": [
   16,
   11,
   2
  ],
  "topics": [
   "recursion",
   "dynamic-programming",
   "integer-representation"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α16.16",
  "path": "questions/labs/lab-lab05-ladder.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab05-ladder.html",
  "statement": "Ένα παιδί ανεβαίνει μια σκάλα και σε κάθε βήμα του ανεβαίνει 1, 2 ή 3 σκαλιά. Έστω ότι η\nσκάλα έχει 5 σκαλιά. Ένας τρόπος να τα ανέβει είναι 1-1-1-1-1, δηλαδή ένα σκαλί την φορά.\nΈνας άλλος είναι ο 2-2-1 (δύο σκαλιά στα πρώτα δύο βήματα και μετά ένα σκαλί). Άλλοι\nπιθανοί τρόποι είναι οι 3-2, 2-3, 3-1-1, κ.ο.κ - σε κάθε περίπτωση ο συνολικός αριθμός\nτων σκαλιών που ανέβηκε πρέπει να ισούται με τον αριθμό των σκαλιών της σκάλας. Γράψτε\nένα πρόγραμμα `ladder.c` το οποίο διαβάζει τον συνολικό αριθμό των σκαλοπατιών και\nεπιστρέφει τον αριθμό των διαφορετικών τρόπων με τους οποίους το παιδί μπορεί να ανέβει\nτην σκάλα. Το πρόγραμμά σας θέλουμε να βγάζει σωστά αποτελέσματα για σκάλες μέχρι 50\nσκαλιά. Λάβετε υπόψη σας ότι στην C δεν μπορούν να αναπαρασταθούν ακέραιοι μεγαλύτεροι\nαπό το $2^{64} - 1$, δεδομένου ότι ο ευρύτερος τύπος ακεραίου που μπορούμε να έχουμε είναι\nο `unsigned long long` (των 8 bytes). Ακολουθούν ενδεικτικές εκτελέσεις:\n\n```text\n$ ./ladder\nPlease provide the number of steps: 4\nThere are 7 different ways to climb the ladder\n$ ./ladder\nPlease provide the number of steps: 5\nThere are 13 different ways to climb the ladder\n$ ./ladder\nPlease provide the number of steps: 6\nThere are 24 different ways to climb the ladder\n$ ./ladder\nPlease provide the number of steps: 50\nThere are 10562230626642 different ways to climb the ladder\n```",
  "hint": "Σκεφτείτε το τελευταίο βήμα του παιδιού: ήταν 1, 2 ή 3 σκαλιά, οπότε οι τρόποι για $n$\nσκαλιά προκύπτουν από τους τρόπους για λιγότερα σκαλιά (όπως στο Fibonacci, αλλά με τρεις\nόρους). Προσέξτε τις βασικές περιπτώσεις για μικρά $n$. Η αφελής αναδρομή δεν θα\nτελειώσει ποτέ για 50 σκαλιά, και το αποτέλεσμα δεν χωράει σε `int`."
 },
 {
  "id": "lab-lab06-judgement",
  "kind": "lab",
  "title": "Πίνακες και συναρτήσεις",
  "source": {
   "title": "Εργαστήριο 6, Άσκηση 4",
   "url": "https://progintro.github.io/lab-material/labs/lab06/",
   "years": [
    2025
   ]
  },
  "chapters": [
   10,
   11
  ],
  "topics": [
   "arrays",
   "functions",
   "redirection"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α10.15",
  "path": "questions/labs/lab-lab06-judgement.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab06-judgement.html",
  "statement": "Σε ένα αγώνισμα υπάρχουν 10 κριτές. Η βαθμολογία του κάθε αγωνιζόμενου βγαίνει από τον\nμέσο όρο 8 κριτών, αφού εξαιρεθεί αυτός με τη μεγαλύτερη και αυτός με τη μικρότερη\nβαθμολογία (για να αποφευχθούν φαινόμενα μεροληψίας, είτε υπέρ είτε κατά ενός αθλητή).\n\n**4.1** Ορίστε τη συνάρτηση `int max_array(int *array, int n)` που επιστρέφει στο όνομά\nτης το μέγιστο στοιχείο του πίνακα ακεραίων `array` διάστασης `n`.\n\n**4.2** Ορίστε τη συνάρτηση `int min_array(int *array, int n)` που επιστρέφει στο όνομά\nτης το ελάχιστο στοιχείο του πίνακα ακεραίων `array` διάστασης `n`.\n\n**4.3** Ορίστε τη συνάρτηση `int sum_array(int *array, int n)` που επιστρέφει στο όνομά\nτης το άθροισμα των στοιχείων του πίνακα ακεραίων `array` διάστασης `n`.\n\n**4.4** Κατασκευάστε το πρόγραμμα `judgement.c` το οποίο να διαβάζει τις 10 βαθμολογίες\nμε χρήση της `scanf()` και να τυπώνει τη βαθμολογία με ακρίβεια 2 δεκαδικών ψηφίων\nσύμφωνα με τον τύπο:\n\n```text\n  Βαθμός = (Άθροισμα - Μέγιστο - Ελάχιστο) / 8\n```\n\nΈστω ένα αρχείο `grades.txt` με τις παρακάτω βαθμολογίες:\n\n```text\n8 2 3 9 0 10 8 3 4 5\n```\n\nΠαράδειγμα εκτέλεσης ακολουθεί:\n\n```text\n$ ./judgement < grades.txt\nSum: 52\nMin: 0\nMax: 10\nAverage: 5.25\n```",
  "hint": "Για μέγιστο και ελάχιστο, αρχικοποιήστε με το πρώτο στοιχείο του πίνακα (όχι με 0) και\nσυγκρίνετε με τα υπόλοιπα. Στον τελικό τύπο και τα τρία μεγέθη είναι ακέραια: αν δεν\nμετατρέψετε σε `double` πριν τη διαίρεση με το 8, θα χάσετε το δεκαδικό μέρος."
 },
 {
  "id": "lab-lab06-myprog",
  "kind": "lab",
  "title": "Πέρασμα δεδομένων μέσω δεικτών",
  "source": {
   "title": "Εργαστήριο 6, Άσκηση 1",
   "url": "https://progintro.github.io/lab-material/labs/lab06/",
   "years": [
    2025
   ]
  },
  "chapters": [
   11,
   3
  ],
  "topics": [
   "pointers",
   "functions"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α11.14",
  "path": "questions/labs/lab-lab06-myprog.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab06-myprog.html",
  "statement": "**1.1** Γράψτε την παρακάτω συνάρτηση μέσα σ' ένα αρχείο `myprog.c` και μεταγλωττίστε\nτο:\n\n```c\nvoid badf(int x, int y, int sum, int diff) {\n  sum = x + y;\n  diff = x - y;\n}\n```\n\nΓράψτε και μία συνάρτηση `main` μέσα σ' ένα αρχείο `myprog.c` η οποία να υλοποιεί την\nπαρακάτω διαδικασία (εκφρασμένη σε ψευδογλώσσα) και μεταγλωττίστε το:\n\n```text\nΌρισε τις ακέραιες μεταβλητές a, b, sum, diff\n\nΘέσε a=5, b=4, sum=0, diff=0\n\nΚάλεσε badf(a, b, sum, diff)\n\nΤύπωσε sum, diff\n```\n\nΔημιουργήστε το εκτελέσιμο πρόγραμμα `myprog` και εκτελέστε το. Τι παρατηρείτε;\nΜπορείτε να εξηγήσετε το αποτέλεσμα;\n\n**1.2** Τροποποιήστε τη συνάρτηση `void badf(int x, int y, int sum, int diff)` ώστε οι\n`sum` και `diff` να είναι δείκτες σε ακεραίους, και μετονομάστε την σε `goodf`.\nΤροποποιήστε την main του προγράμματος ώστε να καλεί τη συνάρτηση `goodf` αντί για την\n`badf`. Τι παρατηρείτε;\n\n**1.3** Χρησιμοποιήστε τη συνάρτηση `scanf()` για να διαβάσετε τους ακέραιους αριθμούς\n`a`, `b` που εμφανίζονται στην main.\n\nΥπενθυμίζουμε ότι η συνάρτηση `scanf()` διαβάζει από την είσοδο δεδομένα προς\nεπεξεργασία. Συντάσσεται με αντίστοιχο τρόπο με την `printf()` δηλαδή:\n\n```c\nscanf(\"%y\", &var);\n```\n\nόπου `y` είναι σύμβολο που αντιστοιχεί στον τύπο δεδομένων της μεταβλητής var (π.χ. `d`\nγια `int`, `f` για `float`, κλπ.). Παρατηρούμε ότι στο δεύτερο όρισμα περνιέται η\nδιεύθυνση της μεταβλητής `var`, για να αποθηκευθεί η καταχώρηση και μετά το πέρας της\nκλήσης.",
  "hint": "Στη C τα ορίσματα περνούν με τιμή: η `badf` αλλάζει τα δικά της αντίγραφα. Για να\nαλλάξει μια συνάρτηση μεταβλητές της `main`, πρέπει να πάρει τις διευθύνσεις τους (`&`)\nκαι να γράψει μέσω του δείκτη (`*`). Είναι ακριβώς ο λόγος που η `scanf` θέλει `&var`."
 },
 {
  "id": "lab-lab06-pointers",
  "kind": "lab",
  "title": "Πίνακες και αριθμητική δεικτών",
  "source": {
   "title": "Εργαστήριο 6, Άσκηση 3",
   "url": "https://progintro.github.io/lab-material/labs/lab06/",
   "years": [
    2025
   ]
  },
  "chapters": [
   11,
   12
  ],
  "topics": [
   "pointer-arithmetic",
   "arrays",
   "pointers"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α11.17",
  "path": "questions/labs/lab-lab06-pointers.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab06-pointers.html",
  "statement": "**3.1** Ορίστε τη συνάρτηση `void print_array(int *array, int n)` που δέχεται σαν όρισμα\nέναν πίνακα ακεραίων και τη διάστασή του και εκτυπώνει τα περιεχόμενά του σε μία γραμμή\nχωρισμένα με στηλογνώμονα (tab).\n\n**3.2** Δημιουργήστε το πρόγραμμα `pointers.c` που δημιουργεί έναν πίνακα 8 θέσεων και\nκάνει πράξεις πάνω σε αυτόν, ακολουθώντας το παρακάτω τμήμα κώδικα:\n\n```text\n01: int i, a[8], *pa;\n02:\n03: for (i=0; i<8; i++)\n04:   a[i] = i*i;\n05:\n06: pa = &a[0];\n07: a[6] = *(a+4);\n08: *(pa+3) = a[5];\n09: a[0] = *((pa++)+2);\n10: *((++pa)+5) = a[1];\n11: *(&a[5]-1) = *(--pa);\n```\n\n**3.3** Εκτυπώστε τα περιεχόμενα του πίνακα, χρησιμοποιώντας τη συνάρτηση\n`print_array()` μετά από τα βήματα 04, 07, 08, 09, 10 και 11 για να παρακολουθήσετε την\nεπίδραση των εντολών στον πίνακα.",
  "hint": "Πριν τρέξετε το πρόγραμμα, προβλέψτε με το χέρι τον πίνακα μετά από κάθε γραμμή και\nμετά συγκρίνετε. Το `*(p+k)` είναι το ίδιο με `p[k]`. Το δύσκολο σημείο είναι οι\nγραμμές 09–11: κρατήστε σημείωση σε ποιο στοιχείο δείχνει το `pa` κάθε στιγμή, και\nθυμηθείτε ότι το `pa++` χρησιμοποιεί την παλιά τιμή ενώ το `++pa` και το `--pa` τη νέα."
 },
 {
  "id": "lab-lab06-sieve",
  "kind": "lab",
  "title": "Το κόσκινο του Ερατοσθένη",
  "source": {
   "title": "Εργαστήριο 6, Άσκηση 2",
   "url": "https://progintro.github.io/lab-material/labs/lab06/",
   "years": [
    2025
   ]
  },
  "chapters": [
   10
  ],
  "topics": [
   "arrays",
   "math-algorithms",
   "loops"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α10.16",
  "path": "questions/labs/lab-lab06-sieve.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab06-sieve.html",
  "statement": "Το [κόσκινο του Ερατοσθένη](https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes) είναι\nένας αλγόριθμος για την εύρεση όλων των πρώτων αριθμών σε ένα εύρος τιμών (από 2 έως\nN - 1). Είναι ένας από τους αρχαιότερους γνωστούς αλγορίθμους και οφείλεται στον Έλληνα\nμαθηματικό και αστρονόμο Ερατοσθένη (276-194 π.Χ.). Ο αλγόριθμος εξετάζει διαδοχικά όλους\nτους ακεραίους και για κάθε αριθμό που συναντά διαγράφει όλα τα πολλαπλάσιά του (αφού\nσίγουρα δεν είναι πρώτοι).\n\nΠαρατηρήστε τα τρία πρώτα βήματα του αλγορίθμου, για N=20.\n\nΌταν ξεκινά ο αλγόριθμος, όλοι οι αριθμοί θεωρούνται πιθανοί πρώτοι (αρχικοποιημένοι στο\n1):\n\n| 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |\n\nΟ «2» είναι πρώτος, διαγραφή των 4, 6, 8, 10, 12, 14, 16, 18, 20 (το σημειώνουμε με 0):\n\n| 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| 1 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 |\n\nΟ «3» είναι πρώτος, διαγραφή των 6, 9, 12, 15, 18:\n\n| 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |\n| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n| 1 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 |\n\nΟ «4» δεν εξετάζεται γιατί έχει αφαιρεθεί σε προηγούμενο βήμα.\n\nΟρίστε έναν πίνακα N θέσεων και αρχικοποιήστε τον με μονάδες. Η διάσταση του πίνακα να\nορίζεται μέσω `#define` με τιμή ίση με 50. Υλοποιήστε το κόσκινο του Ερατοσθένη σύμφωνα\nμε τον αλγόριθμο όπως εκφράζεται παρακάτω σε ψευδογλώσσα:\n\n```text\nΓια i=2 έως N-1 επανάλαβε\n  Θέσε A[i]=1\n\nΓια i=2 έως N-1 επανάλαβε\n  Αν A[i]!=0\n    Για j=2*i έως N-1 με βήμα i επανάλαβε\n      Θέσε A[j]=0\n\nΓια i=2 έως N-1 επανάλαβε\n  Αν το A[i]==1 τύπωσε \"i is a prime number\"\n```\n\nΕκτελέστε το πρόγραμμά σας και επιβεβαιώστε την ορθότητα του αποτελέσματος.",
  "hint": "Η ψευδογλώσσα μεταφράζεται σχεδόν γραμμή προς γραμμή σε βρόχους `for`. Προσέξτε τα όρια:\nο πίνακας έχει θέσεις 0 έως N-1, άρα «έως N-1» σημαίνει συνθήκη `< N`, και ο δείκτης του\nπίνακα είναι ο ίδιος ο αριθμός που εξετάζετε."
 },
 {
  "id": "lab-lab07-array",
  "kind": "lab",
  "title": "Δυναμική δέσμευση μνήμης για μονοδιάστατο πίνακα",
  "source": {
   "title": "Εργαστήριο 7, Άσκηση 2",
   "url": "https://progintro.github.io/lab-material/labs/lab07/",
   "years": [
    2025
   ]
  },
  "chapters": [
   12,
   13
  ],
  "topics": [
   "dynamic-memory",
   "arrays",
   "redirection"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α12.8",
  "path": "questions/labs/lab-lab07-array.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab07-array.html",
  "statement": "**2.1** Κατασκευάστε το πρόγραμμα `array.c` που να διαβάζει από την είσοδο τη διάσταση\nενός μονοδιάστατου πίνακα ακεραίων (έστω `N`), να δεσμεύει χώρο `N` θέσεων δυναμικά και\nέπειτα να τον αρχικοποιεί διαβάζοντας από την είσοδο ακέραιους αριθμούς.\n\n> **Δυναμική δέσμευση μνήμης** για μονοδιάστατο πίνακα\n>\n> Συνάρτηση `void *malloc(size_t size)`\n>\n> Χρήση:\n>\n> - `ΤΔ *p;` — δήλωση ενός δείκτη σε στοιχεία τύπου *ΤΔ*\n> - `p = malloc(N * sizeof(ΤΔ));` — δέσμευση μνήμης για N στοιχεία τύπου *ΤΔ*\n>\n> Η `malloc` επιστρέφει `NULL` σε περίπτωση αποτυχίας δέσμευσης της αιτούμενης μνήμης.\n\n> **Αποδέσμευση μνήμης** για δυναμικά δεσμευμένους πίνακες\n>\n> Συνάρτηση `void free(void *p)`\n>\n> Χρήση: `free(p);` όπου `p` είναι δείκτης σε θέσεις μνήμης που έχουν δεσμευθεί\n> δυναμικά.\n\nΌταν χρησιμοποιούνται οι συναρτήσεις `malloc()` και `free()`, πρέπει να γίνεται\nσυμπερίληψη του αρχείου επικεφαλίδας `stdlib.h`.\n\nΓράψτε μια συνάρτηση `print_array` που να εκτυπώνει τα στοιχεία του πίνακα σε μία γραμμή\nχωρισμένα με στηλογνώμονα (tab).\n\n**2.2** Κατασκευάστε το αρχείο `input.txt` το οποίο να περιέχει `N+1` ακέραιους αριθμούς\nως εξής: Ο πρώτος αριθμός είναι το πλήθος των στοιχείων (`N`) και ακολουθούν οι `N`\nακέραιοι χωρισμένοι με κενά.\n\n**2.3** Εκτελέστε το πρόγραμμα `array` με ανακατεύθυνση εισόδου από το αρχείο\n`input.txt`.\n\n**2.4** Επεκτείνετε το πρόγραμμά σας, με μια συνάρτηση `print_average` ώστε να\nεκτυπώνεται ο μέσος όρος των στοιχείων του πίνακα.",
  "hint": "Διαβάστε πρώτα το `N`, δεσμεύστε και ελέγξτε αμέσως αν η `malloc` επέστρεψε `NULL`. Μετά\nο δείκτης χρησιμοποιείται ακριβώς σαν πίνακας (`p[i]`). Μην ξεχάσετε την `free` στο\nτέλος, και τη μετατροπή σε `double` στον μέσο όρο."
 },
 {
  "id": "lab-lab07-mines",
  "kind": "lab",
  "title": "Δυναμική δέσμευση μνήμης για δισδιάστατο πίνακα",
  "source": {
   "title": "Εργαστήριο 7, Άσκηση 3",
   "url": "https://progintro.github.io/lab-material/labs/lab07/",
   "years": [
    2025
   ]
  },
  "chapters": [
   13,
   12
  ],
  "topics": [
   "multidim-arrays",
   "dynamic-memory",
   "redirection"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α13.8",
  "path": "questions/labs/lab-lab07-mines.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab07-mines.html",
  "statement": "**3.1** Κατασκευάστε το πρόγραμμα `mines.c` που να διαβάζει από την είσοδο τις διαστάσεις\nενός δισδιάστατου πίνακα χαρακτήρων (έστω `N x M`), να δεσμεύει χώρο `N x M` θέσεων\nδυναμικά και έπειτα να τον αρχικοποιεί διαβάζοντας από την είσοδο χαρακτήρες.\n\nΣτην συνέχεια παραθέτουμε τρόπους για να δεσμεύσουμε και να αποδεσμεύσουμε μνήμη δυναμικά\nγια δισδιάστατους πίνακες. Αντίστοιχα μπορείτε να διαχειριστείτε πίνακες με περισσότερες\nδιαστάσεις. Στην τελική εξέταση θα χρειαστεί να διαχειριστείτε δεδομένα δυναμικής φύσης\n(δηλαδή δεδομένα που πρέπει να χωρέσουν σε πίνακες των οποίων τα μεγέθη δεν γνωρίζουμε εκ\nτων προτέρων) και επομένως είναι καλό να εξοικειωθείτε με την διαδικασία\nδέσμευσης/αποδέσμευσης μνήμης.\n\n*Δυναμική δέσμευση μνήμης για δισδιάστατο πίνακα διάστασης N x M:*\n\n```c\n    int i;\n    ΤΔ **p;\n    p = malloc(N * sizeof(ΤΔ *));\n    if (p == NULL) {\n        fprintf(stderr, \"Failed to allocate rows\\n\");\n        exit(1);\n    }\n    for (i = 0 ; i < N ; i++) {\n        p[i] = malloc(M * sizeof(ΤΔ));\n        if (p[i] == NULL) {\n            fprintf(stderr, \"Failed to allocate row %d\\n\", i);\n            exit(1);\n        }\n    }\n```\n\n*Αποδέσμευση μνήμης για δυναμικά δεσμευμένο πίνακα N x M:*\n\n```c\n    int i;\n    for (i = 0 ; i < N ; i++)\n        free(p[i]);\n    free(p);\n```\n\n**3.2** Κατασκευάστε το αρχείο `mines.txt` που αναπαριστά τα δεδομένα ενός ναρκοπεδίου.\nΣυγκεκριμένα, στην πρώτη γραμμή του αρχείου υπάρχουν οι διαστάσεις του ναρκοπεδίου (`N`\nκαι `M`) και μετά ακολουθούν γραμμή-γραμμή τα περιεχόμενα των κελιών, που είναι ο\nχαρακτήρας `.` όταν δεν υπάρχει νάρκη και ο χαρακτήρας `*` όταν υπάρχει νάρκη.\n\n```text\n3 4\n..*.\n.**.\n*.*.\n```\n\n**3.3** Επεκτείνετε το πρόγραμμά σας, ώστε να εκτυπώνονται τα περιεχόμενα του πίνακα που\nδιαβάστηκε. Εκτελέστε το πρόγραμμα σας με ανακατεύθυνση εισόδου από το αρχείο\n`mines.txt`.\n\n**3.4** Επεκτείνετε το πρόγραμμα σας, ώστε να εκτυπώνεται μια τροποποιημένη μορφή του\nναρκοπεδίου, στην οποία, στα κελιά που υπάρχει νάρκη να εμφανίζεται πάλι το `*`, ενώ στα\nκελιά που δεν υπάρχει νάρκη να φαίνεται ένας αριθμός που δείχνει σε *πόσα γειτονικά\nκελιά* υπάρχει νάρκη. Σαν γειτονικά θεωρούνται όχι μόνο συνεχόμενα οριζόντια ή κατακόρυφα\nκελιά, αλλά και συνεχόμενα σε διαγώνια κατεύθυνση. Για παράδειγμα, για το ναρκοπέδιο που\nείδαμε, θα πρέπει να εμφανίζεται η έξοδος:\n\n```text\n13*2\n2**3\n*4*2\n```\n\nΜπορείτε να δοκιμάσετε το πρόγραμμά σας και με μεγαλύτερα πλέγματα προκειμένου να\nεπιβεβαιώσετε ότι λειτουργεί σωστά.",
  "hint": "Κατά την ανάγνωση των κελιών προσέξτε τις αλλαγές γραμμής: αγνοήστε όποιον χαρακτήρα δεν\nείναι `.` ή `*`. Για κάθε κελί εξετάστε τα έως 8 γειτονικά του με δύο μικρούς βρόχους για\nμετατόπιση $-1, 0, +1$ σε γραμμή και στήλη, ελέγχοντας πάντα ότι ο γείτονας είναι μέσα\nστα όρια του πίνακα (οι γωνίες και οι άκρες έχουν λιγότερους γείτονες)."
 },
 {
  "id": "lab-lab07-my_prog",
  "kind": "lab",
  "title": "Εντοπισμός σφάλματος μνήμης με τον gdb",
  "source": {
   "title": "Εργαστήριο 7, Άσκηση 6",
   "url": "https://progintro.github.io/lab-material/labs/lab07/",
   "years": [
    2025
   ]
  },
  "chapters": [
   10,
   24
  ],
  "topics": [
   "debugging",
   "arrays",
   "undefined-behavior"
  ],
  "difficulty": 1,
  "type": "debug",
  "label": "Α10.17",
  "path": "questions/labs/lab-lab07-my_prog.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab07-my_prog.html",
  "statement": "Το παρακάτω πρόγραμμα `my_prog.c` προσπαθεί να μετρήσει πόσοι αριθμοί στον πίνακα `p`\nείναι θετικοί και να υπολογίσει το άθροισμά τους (παρατηρήστε ότι το μέγεθος του πίνακα\nδεν είναι καθορισμένο με άμεσο τρόπο).\n\n```c\n#include <stdio.h>\n\nint main(int argc, char *argv[]) {\n    int p[] = {10, -1, 8, 6, 9, 13, 0, -9, 6};\n    int count = 0, sum = 0, i = 0;\n    do {\n        if (p[i] > 0) {\n            count++;\n            sum += p[count];\n        }\n        i++;\n    } while (1);\n    printf(\"There are %d positive numbers with sum %d\\n\", count, sum);\n    return 0;\n}\n```\n\nΤρέχοντας αυτό το πρόγραμμα, αργά ή γρήγορα θα μας δώσει segmentation fault.\nΜεταγλωττίζοντας με `gcc -g3 -o my_prog my_prog.c` και τρέχοντάς το μέσα στον `gdb`\n(`gdb ./my_prog` και μετά `r`), παίρνουμε κάτι σαν:\n\n```text\nProgram received signal SIGSEGV, Segmentation fault.\n0x080483ac in main () at my_prog.c:7\n7   if (p[i] > 0) {\n```\n\n```text\n(gdb) p p[i]\nCannot access memory at address 0xbf8de000\n(gdb) p i\n$3 = 1279\n```\n\nΔεδομένου ότι το μέγεθος του πίνακα p δεν δηλώνεται ρητά, πώς θα αντιμετωπίζατε αυτό το\nπρόβλημα; Ήταν αυτό αρκετό για να λειτουργήσει σωστά το πρόγραμμα; Αν φταίει και κάτι\nάλλο, προσπαθήστε να το βρείτε με τη χρήση του gdb.\n\nΜε βάση όσα είδατε παραπάνω, διορθώστε το `my_prog.c` ώστε να μην ξεπερνά τα όρια του\nπίνακα και να τερματίζει σωστά.",
  "hint": "Το πλήθος των στοιχείων ενός πίνακα που δηλώθηκε με αρχικοποίηση βγαίνει από το\n`sizeof` όλου του πίνακα διά το `sizeof` ενός στοιχείου, και αυτό πρέπει να μπει στη\nσυνθήκη του βρόχου. Μετά τη διόρθωση των ορίων, ελέγξτε με `p` στον `gdb` ποιο στοιχείο\nπροστίθεται στο `sum` σε κάθε βήμα: είναι αυτό που μόλις ελέγξατε;"
 },
 {
  "id": "lab-lab07-olaf",
  "kind": "lab",
  "title": "Χτίζοντας έναν χιονάνθρωπο (Παλιό θέμα)",
  "source": {
   "title": "Εργαστήριο 7, Άσκηση 4",
   "url": "https://progintro.github.io/lab-material/labs/lab07/",
   "years": [
    2025
   ]
  },
  "chapters": [
   16,
   13
  ],
  "topics": [
   "problem-solving",
   "dynamic-memory",
   "arrays"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α16.17",
  "path": "questions/labs/lab-lab07-olaf.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab07-olaf.html",
  "statement": "Βρισκόμαστε σε έναν χιονισμένο τετράγωνο κήπο διαστάσεων NxN και θέλουμε να φτιάξουμε\nέναν χιονάνθρωπο. Δυστυχώς το χιόνι είναι μαζεμένο σε συγκεκριμένους σωρούς μέσα στον\nκήπο (δεν είναι παντού). Γράψτε ένα πρόγραμμα που αποφασίζει πού πρέπει να φτιάξουμε τον\nχιονάνθρωπό μας ώστε να κάνουμε τον ελάχιστο δυνατό κόπο. Για λόγους απλοποίησης θεωρούμε\nότι όλες οι συντεταγμένες στον κήπο είναι ακέραιες και ότι οι κινήσεις μας μπορούν να\nείναι μόνο πάνω-κάτω-αριστερά-δεξιά (όχι διαγώνια). Το μέγεθος του κήπου και οι\nτοποθεσίες των σωρών χιονιού δίνονται στο πρόγραμμα μέσω αρχείου το οποίο δίνουμε με\nανακατεύθυνση στην πρότυπη είσοδο του προγράμματος. Το αρχείο θα περιέχει την διάσταση\nτου κήπου (N) ακολουθούμενη από τις συντεταγμένες του κάθε σωρού. Παράδειγμα επιτυχούς\nεκτέλεσης ακολουθεί:\n\n```text\n$ gcc -o olaf olaf.c\n$ cat map.txt\n10\n1 1\n6 7\n2 8\n7 2\n$ ./olaf < map.txt\nWe will position the snowman on (4, 4) with a minimum cost of 22.\n```\n\nΣτην [οπτικοποίηση της επιλογής μας](https://progintro.github.io/lab-material/labs/lab07/img/media/map.png)\nο χιονάνθρωπος βρίσκεται στην θέση \"καρότο\" ενώ οι σωροί με τα χιόνια απεικονίζονται με\nτους κύκλους. Από τους δύο πάνω σωρούς παρατηρούμε ότι χρειαζόμαστε 6 βήματα για να\nφτάσουμε τον χιονάνθρωπο ενώ από τους δύο κάτω χρειαζόμαστε 5 - σύνολο\n(6 + 6 + 5 + 5 =) 22. Παρατηρήστε ότι μπορεί να υπάρχουν περισσότερες από μία βέλτιστες\nτοποθετήσεις, χρειάζεται να βρούμε μόνο μία από αυτές. Για λόγους απλότητας ο\nχιονάνθρωπος μπορεί να τοποθετηθεί πάνω σε έναν σωρό (και τα βήματα που απαιτούνται σε\nαυτήν την περίπτωση είναι 0).",
  "hint": "Η απόσταση με κινήσεις μόνο πάνω-κάτω-αριστερά-δεξιά είναι η απόσταση Manhattan,\n$|x_1 - x_2| + |y_1 - y_2|$. Το πλήθος των σωρών δεν είναι γνωστό από πριν, οπότε\nδιαβάστε τις συντεταγμένες μέχρι το τέλος της εισόδου σε πίνακα που μεγαλώνει δυναμικά.\nΜια εξαντλητική λύση δοκιμάζει κάθε θέση του κήπου και κρατά την καλύτερη. Για μεγάλο\nN, σκεφτείτε ότι οι δύο συντεταγμένες βελτιστοποιούνται ανεξάρτητα η μία από την άλλη."
 },
 {
  "id": "lab-lab07-pacman",
  "kind": "lab",
  "title": "Κινήσεις σε πλέγμα (Παλιό θέμα)",
  "source": {
   "title": "Εργαστήριο 7, Άσκηση 5",
   "url": "https://progintro.github.io/lab-material/labs/lab07/",
   "years": [
    2025
   ]
  },
  "chapters": [
   13,
   12
  ],
  "topics": [
   "multidim-arrays",
   "dynamic-memory",
   "command-line-args",
   "simulation"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α13.9",
  "path": "questions/labs/lab-lab07-pacman.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab07-pacman.html",
  "statement": "Γράψτε ένα πρόγραμμα που παίρνει δύο εισόδους: (1) το περιεχόμενο μιας πίστας pacman από\nτην πρότυπη είσοδο και (2) τις κινήσεις που πρέπει να κάνει ο pacman πάνω στο πλέγμα ως\nτο πρώτο όρισμα και τυπώνει την τελική κατάσταση του παιχνιδιού μετά από αυτές τις\nκινήσεις. Η πίστα pacman θα έχει την ακόλουθη μορφή:\n\n1. Διάσταση του πλέγματος του παιχνιδιού (δεκαδικός ακέραιος).\n2. Τετράγωνο πλέγμα με χαρακτήρες '.' και ένα 'P' για την αρχική θέση του pacman. Όλοι οι\n   άλλοι χαρακτήρες αγνοούνται.\n\nΟι κινήσεις που πρέπει να κάνει ο pacman θα αποτελούνται από τους 4 χαρακτήρες 'U' (Up),\n'D' (Down), 'L' (Left), 'R' (Right). Όταν ο pacman κινείται σε κάποια θέση, τότε η τελεία\n('.') σε εκείνη την θέση εξαφανίζεται. Η πίστα είναι τόρος, δηλαδή αν είσαι στην\nτελευταία γραμμή της και κινηθείς προς τα κάτω (D) τότε μεταφέρεσαι στην πρώτη γραμμή.\nΑντίστοιχα για κινήσεις αριστερά-δεξιά. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ gcc -o pacman pacman.c\n$ cat level.txt\n7\n.......\n.......\n..P....\n.......\n.......\n.......\n.......\n$ ./pacman RRD < level.txt\n.......\n.......\n..   ..\n....P..\n.......\n.......\n.......\n$ ./pacman RRDDLL < level.txt\n.......\n.......\n..   ..\n.... ..\n..P  ..\n.......\n.......\n$ ./pacman RRDDLLUU < level.txt\n.......\n.......\n..P  ..\n.. . ..\n..   ..\n.......\n.......\n$ ./pacman RRDDLLUULLLL < level.txt\n.......\n.......\n     P\n.. . ..\n..   ..\n.......\n.......\n\n```",
  "hint": "Κρατήστε την πίστα σε δισδιάστατο πίνακα χαρακτήρων δεσμευμένο δυναμικά (η διάσταση\nδιαβάζεται πρώτη) και διαβάστε τα κελιά αγνοώντας κάθε χαρακτήρα εκτός από `.` και `P`.\nΔιατρέξτε το `argv[1]` χαρακτήρα-χαρακτήρα: σε κάθε κίνηση αδειάστε το τρέχον κελί και\nμετακινήστε τη θέση. Για την αναδίπλωση του τόρου χρησιμοποιήστε υπόλοιπο διαίρεσης,\nπροσέχοντας ότι στη C το υπόλοιπο αρνητικού αριθμού είναι αρνητικό."
 },
 {
  "id": "lab-lab07-twodim",
  "kind": "lab",
  "title": "Δισδιάστατοι πίνακες",
  "source": {
   "title": "Εργαστήριο 7, Άσκηση 1",
   "url": "https://progintro.github.io/lab-material/labs/lab07/",
   "years": [
    2025
   ]
  },
  "chapters": [
   12
  ],
  "topics": [
   "multidim-arrays",
   "loops",
   "functions"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α12.10",
  "path": "questions/labs/lab-lab07-twodim.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab07-twodim.html",
  "statement": "**1.1** Κατασκευάστε το πρόγραμμα `twodim.c` που ορίζει στατικά έναν πίνακα A διαστάσεων\n6 x 10 και αρχικοποιεί το στοιχείο `A[i][j]` που βρίσκεται στη γραμμή i και στη στήλη j,\nσύμφωνα με τον τύπο:\n\n$$A[i][j] = 5\\cdot (5 - i) + j\\cdot (9-j)$$\n\nΦτιάξτε μια συνάρτηση `print_array` που να εκτυπώνει τον πίνακα κατά γραμμές, με τα\nστοιχεία κάθε γραμμής χωρισμένα με στηλογνώμονα (tab).\n\n**1.2** Επεκτείνετε το πρόγραμμα `twodim.c` με μια συνάρτηση `print_transposed` ώστε να\nεκτυπώνει *και* τον ανάστροφο του πίνακα, δηλαδή αυτόν που έχει στήλες τις γραμμές του\nαρχικού και γραμμές τις στήλες του αρχικού (αυτή είναι μια κατεξοχήν άσκηση\nπρογραμματιστικής συνέντευξης).\n\nΕπομένως, αν ένας αρχικός πίνακας 3 x 5 που εκτυπώνεται έτσι:\n\n```text\n1 4 6 7 8\n5 6 7 1 3\n1 0 4 7 2\n```\n\nόταν τον τυπώνετε ανάστροφα, θέλουμε να τυπώνεται 5 x 3, δηλαδή ως εξής:\n\n```text\n1 5 1\n4 6 0\n6 7 4\n7 1 7\n8 3 2\n```\n\n**1.3** Επεκτείνετε το πρόγραμμα `twodim.c` με μια συνάρτηση `print_reverse` ώστε να\nεκτυπώνει τα στοιχεία κάθε γραμμής του αρχικού πίνακα με αντίστροφη σειρά. Για\nπαράδειγμα, αν ο αρχικός σας πίνακας είναι και πάλι:\n\n```text\n1 4 6 7 8\n5 6 7 1 3\n1 0 4 7 2\n```\n\nόταν τυπωθεί με αντίστροφη σειρά, θέλουμε να τυπώσει κάτι τέτοιο:\n\n```text\n8 7 6 4 1\n3 1 7 6 5\n2 7 4 0 1\n```\n\n**1.4** Επεκτείνετε το πρόγραμμα `twodim.c` ώστε να εκτυπώνει όλα τα στοιχεία του πίνακα\nσε μία σειρά, διασχίζοντάς τον με έναν\n[οφιοειδή](https://el.wiktionary.org/wiki/%CE%BF%CF%86%CE%B9%CE%BF%CE%B5%CE%B9%CE%B4%CE%AE%CF%82)\nτρόπο, όπως φαίνεται στο παράδειγμα:\n\nΟ αρχικός πίνακας:\n\n```text\n1 4 6 7 8\n5 6 7 1 3\n1 0 4 7 2\n```\n\nθέλουμε να εκτυπωθεί ως εξής:\n\n```text\n1 4 6 7 8 3 1 7 6 5 1 0 4 7 2\n```",
  "hint": "Όταν περνάτε στατικό δισδιάστατο πίνακα σε συνάρτηση, η δεύτερη διάσταση πρέπει να\nφαίνεται στον τύπο της παραμέτρου (ορίστε τις διαστάσεις με `#define`). Όλες οι\nπαραλλαγές είναι δύο εμφωλευμένοι βρόχοι: στον ανάστροφο αλλάζει ποιος δείκτης είναι\nεξωτερικός, στην αντίστροφη η εσωτερική μέτρηση πάει προς τα πίσω, και στην οφιοειδή η\nφορά της γραμμής εξαρτάται από το αν η γραμμή είναι άρτια ή περιττή."
 },
 {
  "id": "lab-lab08-argcalc",
  "kind": "lab",
  "title": "Ορίσματα γραμμής εντολής",
  "source": {
   "title": "Εργαστήριο 8, Άσκηση 2",
   "url": "https://progintro.github.io/lab-material/labs/lab08/",
   "years": [
    2025
   ]
  },
  "chapters": [
   12,
   8
  ],
  "topics": [
   "command-line-args",
   "conditionals",
   "operators"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α12.9",
  "path": "questions/labs/lab-lab08-argcalc.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab08-argcalc.html",
  "statement": "**2.1** Κατασκευάστε το πρόγραμμα `argcalc.c` που να εκτελεί απλές αριθμητικές πράξεις\n(πρόσθεση, αφαίρεση, πολλαπλασιασμό, πηλίκο διαίρεσης και υπόλοιπο διαίρεσης) μεταξύ\nακεραίων. Οι πράξεις που θα γίνονται να δίνονται σαν ορίσματα στη γραμμή εντολής.\n\nΠαραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ ./argcalc 12 + 18\n30\n$ ./argcalc 70 % 12\n10\n```\n\n> Προσοχή: τον χαρακτήρα `*` τον επεκτείνει το shell πριν φτάσει στο πρόγραμμά μας,\n> οπότε για τον πολλαπλασιασμό τον γράφουμε σε εισαγωγικά (`./argcalc 6 '*' 7`) ή με\n> ανάποδη κάθετο (`./argcalc 6 \\* 7`).\n\n**Ορίσματα Γραμμής Εντολής**\n\nΟρισμός της συνάρτησης `main`:\n\n```c\n    int main(int argc, char *argv[])\n```\n\n- Η μεταβλητή `argc` αρχικοποιείται με το πλήθος των ορισμάτων `N + 1`, τα οποία\n  βρίσκονται στις θέσεις `argv[0]`, ..., `argv[N]` του πίνακα συμβολοσειρών `argv`. Το\n  `argv[0]` είναι το όνομα του προγράμματος και το `argv[N+1]` είναι `NULL`.\n- Η συνάρτηση `int atoi(const char *s)` επιστρέφει στο όνομά της την αριθμητική τιμή που\n  αντιστοιχεί στην (αριθμητική) συμβολοσειρά `s`.",
  "hint": "Ελέγξτε πρώτα ότι το `argc` είναι 4. Οι αριθμοί είναι τα `argv[1]` και `argv[3]` (ως\nσυμβολοσειρές, άρα χρειάζονται μετατροπή), και ο τελεστής είναι ο πρώτος χαρακτήρας του\n`argv[2]`, πάνω στον οποίο μπορείτε να κάνετε `switch`. Σκεφτείτε τι πρέπει να γίνει όταν\nο διαιρέτης είναι 0."
 },
 {
  "id": "lab-lab08-legolas",
  "kind": "lab",
  "title": "Πετυχαίνοντας τον στόχο (Παλιό θέμα)",
  "source": {
   "title": "Εργαστήριο 8, Άσκηση 3",
   "url": "https://progintro.github.io/lab-material/labs/lab08/",
   "years": [
    2025
   ]
  },
  "chapters": [
   12,
   2
  ],
  "topics": [
   "command-line-args",
   "loops",
   "integer-representation"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α12.11",
  "path": "questions/labs/lab-lab08-legolas.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab08-legolas.html",
  "statement": "Γράψτε ένα πρόγραμμα το οποίο παίρνει ως ορίσματα από την γραμμή εντολών έναν\nακέραιο-στόχο (goal το `argv[1]`) και στην συνέχεια ένα σύνολο υποψηφίων ακεραίων\n(candidates) και τυπώνει όλους τους συνδυασμούς 3 υποψηφίων των οποίων το άθροισμα\nισούται με τον στόχο. Η σειρά με την οποία εκτυπώνονται τα αποτελέσματα δεν έχει σημασία\nγια την ορθότητα του προγράμματος. Παραδείγματα εκτέλεσης ακολουθούν:\n\n```text\n$ gcc -o legolas legolas.c\n$ ./legolas 42 19 21 3 5 12\nNo combination of candidates leads to 42\n$ ./legolas 42 19 21 3 5 12 11\nCandidates combination found: 19 + 12 + 11 = 42\n$ ./legolas 42 27 25 12 31 5 26 40 34 3 18\nCandidates combination found: 27 + 12 + 3 = 42\nCandidates combination found: 25 + 12 + 5 = 42\nCandidates combination found: 5 + 34 + 3 = 42\n$ ./legolas 37372082074 9238742398 82934723 27893492387 127863435 239847289\nCandidates combination found: 9238742398 + 27893492387 + 239847289 = 37372082074\n```",
  "hint": "Διαλέξτε τριάδες διαφορετικών θέσεων με τρεις εμφωλευμένους βρόχους όπου κάθε δείκτης\nξεκινά μετά τον προηγούμενο, ώστε κάθε συνδυασμός να εμφανίζεται μία φορά. Το τελευταίο\nπαράδειγμα έχει αριθμούς που δεν χωρούν σε `int`, οπότε η μετατροπή από συμβολοσειρά\nπρέπει να γίνει σε `long long`. Μην ξεχάσετε το μήνυμα όταν δεν βρεθεί κανένας\nσυνδυασμός."
 },
 {
  "id": "lab-lab08-string",
  "kind": "lab",
  "title": "Επεξεργασία συμβολοσειρών",
  "source": {
   "title": "Εργαστήριο 8, Άσκηση 1",
   "url": "https://progintro.github.io/lab-material/labs/lab08/",
   "years": [
    2025
   ]
  },
  "chapters": [
   14,
   12
  ],
  "topics": [
   "strings",
   "pointers"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α14.9",
  "path": "questions/labs/lab-lab08-string.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab08-string.html",
  "statement": "**1.1** Κατασκευάστε το πρόγραμμα `string.c`, το οποίο θα συμπεριλαμβάνει το αρχείο\nεπικεφαλίδας `string.h` και θα πραγματοποιεί το σενάριο που ακολουθεί.\n\n**1.2** Ορίστε τις συμβολοσειρές `strA` και `strB` με στατική ή δυναμική δέσμευση μνήμης\n80 χαρακτήρων.\n\n**1.3** Αντιγράψτε στην `strA` τη συμβολοσειρά `\"This is a string.\"` και στην `strB` τη\nσυμβολοσειρά `\"This is another string.\"` χρησιμοποιώντας την συνάρτηση `strcpy`.\n\n```c\n    char *strcpy(char *s1, const char *s2)\n```\n\nΗ συνάρτηση `strcpy` αντιγράφει τη συμβολοσειρά `s2` στην `s1` και επιστρέφει την τιμή\nτου δείκτη (char *) στον οποίο έκανε την αντιγραφή (σε αυτό το παράδειγμα επιστρέφει την\nτιμή της μεταβλητής `s1`). Χρησιμοποιώντας την `printf(\"%p %p %p\\n\", ...)` τυπώστε τους\nτρεις δείκτες που συμμετέχουν στην κλήση αυτής της συνάρτησης (`s1`, `s2` και την τιμή\nεπιστροφής της `strcpy`).\n\n**1.4** Υλοποιήστε τη συνάρτηση `int mystrlen(char *str)` η οποία δέχεται σαν όρισμα μία\nσυμβολοσειρά και επιστρέφει το μήκος της (χωρίς να συμπεριλαμβάνεται ο χαρακτήρας τέλους\nσυμβολοσειράς `'\\0'`).\n\n**1.5** Υλοποιήστε τη συνάρτηση `char *mystrcat(char *s1, char *s2)` η οποία προσαρτά\nένα αντίγραφο της συμβολοσειράς `s2` στο τέλος της s1 και επιστρέφει στο όνομά της έναν\nδείκτη στην `s1`.\n\n**1.6** Εκτυπώστε τις δύο συμβολοσειρές και το μήκος τους. Υπολογίστε το μήκος της `strA`\nμέσω της συνάρτησης `mystrlen` που υλοποιήσατε παραπάνω και το μήκος της `strB` μέσω της\nσυνάρτησης `strlen` της C.\n\n```c\n    size_t strlen(const char *s)\n```\n\nΗ συνάρτηση `strlen` επιστρέφει στο όνομά της το μήκος της συμβολοσειράς `s` (χωρίς να\nμετράται το τελικό `'\\0'`).\n\n**1.7** Συγκρίνετε αλφαβητικά τις συμβολοσειρές `strA` και `strB` εκτυπώνοντας κατάλληλο\nμήνυμα.\n\n```c\n    int strcmp(const char *s1, const char *s2)\n```\n\nΗ συνάρτηση `strcmp` συγκρίνει τις συμβολοσειρές `s1` και `s2` χαρακτήρα προς χαρακτήρα\nμε βάση τους αντίστοιχους ASCII κωδικούς. Επιστρέφει:\n\n1. `= 0`, αν οι συμβολοσειρές είναι ίδιες\n2. `> 0`, αν η `s1` είναι λεξικογραφικά «μεγαλύτερη» της `s2`\n3. `< 0`, αν η `s1` είναι λεξικογραφικά «μικρότερη» της `s2`\n\n**1.8** Προσαρτήστε τη συμβολοσειρά `strB` στο τέλος της `strA` (χρησιμοποιώντας τη\nσυνάρτηση `mystrcat` που υλοποιήσατε παραπάνω) και εκτυπώστε το αποτέλεσμα της\nπροσάρτησης. Στη συνέχεια, προσαρτήστε τη νέα τιμή της συμβολοσειράς `strA` στο τέλος της\n`strB` (χρησιμοποιώντας τη συνάρτηση `strcat` της C) και εκτυπώστε το αποτέλεσμα της\nπροσάρτησης.\n\n```c\n    char *strcat(char *s1, const char *s2)\n```\n\nΗ `strcat` προσαρτά / συνενώνει (concatenates) ένα αντίγραφο της συμβολοσειράς `s2` στο\nτέλος της `s1` και επιστρέφει στο όνομά της έναν δείκτη στην `s1`.\n\n**1.9** Χρησιμοποιήστε τη συνάρτηση `strtok` για να εκτυπώσετε μία προς μία τις λέξεις\nπου εμφανίζονται στην τελική συμβολοσειρά `strB`, χωρίς τους χαρακτήρες στίξης.\n\n```c\n    char *strtok(char *string, const char *delim)\n```\n\nΑν το `string` δεν είναι `NULL`, η `strtok` ψάχνει στο string για την πρώτη εμφάνιση\nσυμβολοσειράς που περιορίζεται από έναν από τους χαρακτήρες που εμφανίζονται στη\nσυμβολοσειρά `delim`. Αν υπάρχει, αντικαθιστά τον χαρακτήρα που βρέθηκε στο string, με\n`'\\0'` και επιστρέφει έναν δείκτη στην αρχή του `string`.\n\nΣε κάθε επόμενη κλήση της, η `strtok` καλείται με `NULL` στο πρώτο όρισμα και συνεχίζει\nτη λειτουργία της από το σημείο που η τελευταία κλήση βρήκε τον χαρακτήρα διαχωρισμού.\nΈνα παράδειγμα χρήσης ακολουθεί με ένα\n[quote](http://www.quotationspage.com/quote/31293.html):\n\n```c\n  char *p, s[] = \"Little by little, one Little travels far.\";\n  p = strtok(s, \" ,.\");\n  while(p != NULL) {\n    printf(\"%s\\n\", p);\n    p = strtok(NULL, \" ,.\");\n  }\n```\n\nΠροσθέστε το παραπάνω σε μια συνάρτηση `strtok_example` και τρέξτε την από την `main`.\nΣτο `stdout` θα πρέπει να δείτε μια ακολουθία της μορφής:\n\n```text\nLittle\nby\nlittle\none\nLittle\ntravels\nfar\n```",
  "hint": "Μια συμβολοσειρά τελειώνει στο `'\\0'`: η `mystrlen` προχωρά μέχρι να το βρει, και η\n`mystrcat` βρίσκει πρώτα το τέλος της `s1` και από εκεί αντιγράφει την `s2` μαζί με το\nτελικό `'\\0'`. Στο 1.8 λογαριάστε τα μήκη: χωράει το αποτέλεσμα των δύο συνενώσεων στους\n80 χαρακτήρες της `strB`; Αν όχι, γράφετε έξω από τον πίνακα."
 },
 {
  "id": "lab-lab08-wages",
  "kind": "lab",
  "title": "Υπολογισμός μισθών",
  "source": {
   "title": "Εργαστήριο 8, Άσκηση 4",
   "url": "https://progintro.github.io/lab-material/labs/lab08/",
   "years": [
    2025
   ]
  },
  "chapters": [
   11,
   24
  ],
  "topics": [
   "debugging",
   "dynamic-memory",
   "pointers"
  ],
  "difficulty": 2,
  "type": "debug",
  "label": "Α11.18",
  "path": "questions/labs/lab-lab08-wages.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab08-wages.html",
  "statement": "Το παρακάτω πρόγραμμα δημιουργεί έναν πίνακα με τυχαίους μισθούς και βρίσκει το μέσο\nμισθό, παραλείποντας όσα κελιά έχουν τιμή μικρότερη ή ίση του μηδενός. Όμως το πρόγραμμα\nδίνει segmentation fault, ενώ έχει και λογικά λάθη. Αποσφαλματώστε το με τη βοήθεια ενός\ndebugger και διορθώστε το.\n\n```c\n#include <stdio.h>\n\n#define N 100\n\nint main(int argc, char ** argv) {\n  int i = 0, sum = 0;\n  int *wages = NULL;\n  srand(N);\n  for (i = 0 ; i < N ; i++)\n    wages[i] = 700 + (rand()%2301) - 1000;\n  while (wages[i] > 0 && i < N) {\n    sum += wages[i];\n    i++;\n  }\n  printf(\"Average wage is %0.2f\\n\", sum/N);\n  return 0;\n}\n```\n\n**Συμβουλές**\n\nΌποτε δουλεύετε με δείκτες στα προγράμματά σας, να έχετε πάντα στο νου σας τα εξής:\n\n1. Ένας δείκτης δεν αρχικοποιείται σε NULL, αλλά δείχνει σε κάποια τυχαία θέση μνήμης.\n   Είναι πολύ σημαντικό όποτε δηλώνουμε ένα δείκτη να του δίνουμε τιμή NULL, έτσι ώστε\n   όποτε χρησιμοποιείται, να ελέγχουμε πρώτα αν η τιμή του είναι NULL.\n2. Κάθε συμβολοσειρά `char *` πρέπει να έχει αρκετό χώρο για να χωρέσει όλους τους\n   χαρακτήρες που θέλουμε να βάλουμε συν το τελικό `\\0`.\n3. Όποτε χρησιμοποιούμε πίνακες, πάντα προσέχουμε να μη βγούμε έξω από τα όριά τους.",
  "hint": "Τρέξτε το στον `gdb` και δείτε σε ποια γραμμή σκάει και πού δείχνει ο `wages`. Το\nsegfault είναι μόνο το πρώτο πρόβλημα: ιχνηλατήστε μετά τον βρόχο `while` (με ποια τιμή\nτου `i` ξεκινά, τι κάνει όταν συναντήσει μη θετικό μισθό) και τον υπολογισμό του μέσου\nόρου, και μεταγλωττίστε με `-Wall` για να δείτε τις προειδοποιήσεις."
 },
 {
  "id": "lab-lab09-grades-tree",
  "kind": "lab",
  "title": "Καθαρή διαχείριση μνήμης",
  "source": {
   "title": "Εργαστήριο 9, Άσκηση 5",
   "url": "https://progintro.github.io/lab-material/labs/lab09/",
   "years": [
    2025
   ]
  },
  "chapters": [
   25,
   21,
   22
  ],
  "topics": [
   "debugging",
   "dynamic-memory",
   "linked-lists",
   "trees"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α25.1",
  "path": "questions/labs/lab-lab09-grades-tree.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab09-grades-tree.html",
  "statement": "Η άσκηση βασίζεται στο παράρτημα «Αποσφαλμάτωση προγραμμάτων (Πράξη 5η)» του\n[εργαστηρίου](https://progintro.github.io/lab-material/labs/lab09/), που δείχνει πώς\nτρέχουμε ένα πρόγραμμα κάτω από το valgrind:\n\n```text\ngcc -g3 -o grades grades.c\nvalgrind --leak-check=full ./grades\n```\n\nκαι πώς διαβάζουμε τις κατηγορίες διαρροών (`definitely lost`, `indirectly lost`,\n`possibly lost`, `still reachable`). Η μόνη έξοδος που θεωρούμε καθαρή είναι:\n\n```text\n==2578== HEAP SUMMARY:\n==2578==     in use at exit: 0 bytes in 0 blocks\n==2578==   total heap usage: 5 allocs, 5 frees, 4,160 bytes allocated\n==2578==\n==2578== All heap blocks were freed -- no leaks are possible\n==2578==\n==2578== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)\n```\n\n**5.1** Καθαρίστε τις δομές σας.\n\nΕπιστρέψτε στις Ασκήσεις 3 και 4 αυτού του εργαστηρίου. Καμία από τις δύο δεν αποδεσμεύει\nτη μνήμη που δεσμεύει.\n\n**5.1.1** Γράψτε τη συνάρτηση `void free_list(Listptr ptr)` και καλέστε την από τη `main`\nτου `grades.c`. Επιβεβαιώστε με valgrind ότι βλέπετε το μήνυμα `All heap blocks were\nfreed`.\n\n**5.1.2** Γράψτε την **αναδρομική** συνάρτηση `void free_tree(Treeptr p)` για το\n`tree.c`. Προσοχή στη σειρά: πρέπει να αποδεσμεύσετε πρώτα τα υποδένδρα και μετά τον\nκόμβο. Τι θα δείξει το valgrind αν το κάνετε ανάποδα;\n\n**5.2** Ξαναδείτε ένα παλιό σφάλμα.\n\nΣτο εργαστήριο 8 αποσφαλματώσαμε το `wages.c` με τη βοήθεια ενός debugger. Τρέξτε τώρα\nτην **αρχική, λανθασμένη** έκδοση του με valgrind. Ποιο ακριβώς μήνυμα σας δίνει, και σε\nποια γραμμή; Σας οδηγεί πιο γρήγορα στο πρόβλημα από ό,τι ο `gdb`;",
  "hint": "Στη λίστα, κρατήστε τον δείκτη στον επόμενο κόμβο πριν αποδεσμεύσετε τον τρέχοντα,\nαλλιώς διαβάζετε μνήμη που μόλις ελευθερώσατε. Στο δένδρο, η σειρά είναι μια post-order\nδιάσχιση: αν ελευθερώσετε πρώτα τον κόμβο, τα `left` και `right` του διαβάζονται από\nαποδεσμευμένη μνήμη."
 },
 {
  "id": "lab-lab09-grades",
  "kind": "lab",
  "title": "Συνδεδεμένες λίστες",
  "source": {
   "title": "Εργαστήριο 9, Άσκηση 3",
   "url": "https://progintro.github.io/lab-material/labs/lab09/",
   "years": [
    2025
   ]
  },
  "chapters": [
   21,
   19
  ],
  "topics": [
   "linked-lists",
   "structs",
   "dynamic-memory"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α21.7",
  "path": "questions/labs/lab-lab09-grades.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab09-grades.html",
  "statement": "**3.1** Κατασκευάστε το πρόγραμμα `grades.c` και ορίστε μία αυτοαναφορική δομή λίστας\nακεραίων αριθμών.\n\n```c\ntypedef struct listnode *Listptr;\n\nstruct listnode {\n    int data;\n    Listptr next;\n};\n```\n\n**3.2** Κατασκευάστε τη συνάρτηση:\n\n```c\nvoid insert_at_start(Listptr *ptr, int grade);\n```\n\nΗ συνάρτηση θα προσθέτει έναν βαθμό στην αρχή της λίστας. Τροποποιήστε τη `main` για να\nδιαβάζει βαθμούς από το πληκτρολόγιο και να τους προσθέτει στη λίστα.\n\n**3.3** Κατασκευάστε τη συνάρτηση:\n\n```c\nfloat average(Listptr ptr);\n```\n\nΗ συνάρτηση θα διασχίζει τα περιεχόμενα της λίστας και θα υπολογίζει τον μέσο όρο των\nβαθμών που είναι αποθηκευμένοι σε αυτήν.",
  "hint": "Η `insert_at_start` αλλάζει την κεφαλή της λίστας, γι' αυτό παίρνει δείκτη στον δείκτη\nτης κεφαλής: δεσμεύει νέο κόμβο, τον κάνει να δείχνει στην παλιά κεφαλή και μετά\nενημερώνει την κεφαλή. Η `average` προχωρά ακολουθώντας τα `next` μέχρι το `NULL`,\nμετρώντας και αθροίζοντας. Σκεφτείτε τι πρέπει να επιστρέψει για κενή λίστα."
 },
 {
  "id": "lab-lab09-person",
  "kind": "lab",
  "title": "Δομές και δείκτες",
  "source": {
   "title": "Εργαστήριο 9, Άσκηση 2",
   "url": "https://progintro.github.io/lab-material/labs/lab09/",
   "years": [
    2025
   ]
  },
  "chapters": [
   19,
   13,
   14
  ],
  "topics": [
   "structs",
   "dynamic-memory",
   "strings"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α19.10",
  "path": "questions/labs/lab-lab09-person.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab09-person.html",
  "statement": "**2.1** Δημιουργήστε το αρχείο `person.c` και ορίστε τη δομή `person` που αποθηκεύει το\nόνομα, το επώνυμο και το πατρώνυμο ενός ατόμου.\n\n```c\nstruct person {\n    char *fname;\n    char *lname;\n    char *mname;\n};\n```\n\n**2.2** Κατασκευάστε τη συνάρτηση:\n\n```c\nstruct person *person_init(char *firstname, char *lastname, char *middlename);\n```\n\nΗ συνάρτηση θα δεσμεύει χώρο για μία δομή τύπου `person`, θα την αρχικοποιεί και θα\nεπιστρέφει τη διεύθυνσή της. Καλέστε τη συνάρτηση από την `main` για να καταχωρίσετε τα\nστοιχεία του πατέρα σας.\n\n**2.3** Ορίστε τη συνάρτηση:\n\n```c\nstruct person *childof(struct person father, char *newname);\n```\n\nΗ συνάρτηση θα καταχωρεί τα στοιχεία ενός παιδιού με μικρό όνομα `newname`,\nχρησιμοποιώντας τον πατέρα του `father`. Καλέστε τη συνάρτηση από την `main` για να\nκαταχωρίσετε τα στοιχεία σας.",
  "hint": "Τα πεδία είναι δείκτες: αποφασίστε αν θα αντιγράψετε τα ονόματα σε δική τους δυναμική\nμνήμη (`malloc` με `strlen + 1` και `strcpy`) ή αν απλώς θα κρατήσετε τους δείκτες που\nσας δόθηκαν, και σκεφτείτε τι γίνεται στη δεύτερη περίπτωση αν αλλάξει ο αρχικός\nπίνακας. Στην `childof`, ποιο όνομα του πατέρα γίνεται πατρώνυμο του παιδιού και ποιο\nκρατιέται ως επώνυμο;"
 },
 {
  "id": "lab-lab09-point",
  "kind": "lab",
  "title": "Δομές και συναρτήσεις",
  "source": {
   "title": "Εργαστήριο 9, Άσκηση 1",
   "url": "https://progintro.github.io/lab-material/labs/lab09/",
   "years": [
    2025
   ]
  },
  "chapters": [
   19
  ],
  "topics": [
   "structs",
   "functions"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α19.9",
  "path": "questions/labs/lab-lab09-point.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab09-point.html",
  "statement": "**1.1** Κατασκευάστε το αρχείο `point.c` και ορίστε σε αυτό τη δομή `point` που\nαποθηκεύει τις συντεταγμένες (τύπου `double`) ενός σημείου στον δισδιάστατο χώρο.\n\n**1.2** Ορίστε τη συνάρτηση:\n\n```c\nstruct point middle(struct point a, struct point b);\n```\n\nΗ συνάρτηση θα υπολογίζει και θα επιστρέφει το σημείο που βρίσκεται στο μέσο του\nευθυγράμμου τμήματος με άκρα τα σημεία `a` και `b`.\n\n**1.3** Υπολογίστε και τυπώστε το μέσο του ευθυγράμμου τμήματος με άκρα τα σημεία\n`(1.2,5.4)` και `(7.3,1.8)`.",
  "hint": "Οι δομές περνούν και επιστρέφονται με τιμή, όπως οι απλές μεταβλητές: η `middle` φτιάχνει\nμια τοπική `struct point`, συμπληρώνει τα πεδία της με τον μέσο όρο των αντίστοιχων\nσυντεταγμένων και την επιστρέφει. Στα πεδία φτάνετε με τον τελεστή `.`."
 },
 {
  "id": "lab-lab09-tree",
  "kind": "lab",
  "title": "Δυαδικά δένδρα",
  "source": {
   "title": "Εργαστήριο 9, Άσκηση 4",
   "url": "https://progintro.github.io/lab-material/labs/lab09/",
   "years": [
    2025
   ]
  },
  "chapters": [
   22,
   21,
   11
  ],
  "topics": [
   "trees",
   "recursion",
   "dynamic-memory"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α22.14",
  "path": "questions/labs/lab-lab09-tree.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab09-tree.html",
  "statement": "**4.1** Δημιουργήστε το αρχείο `tree.c` και ορίστε μία αυτοαναφορική δομή δυαδικού\nδένδρου ακεραίων αριθμών.\n\n```c\ntypedef struct tnode *Treeptr;\n\nstruct tnode {\n    int data;\n    Treeptr left;\n    Treeptr right;\n};\n```\n\n**4.2** Ένα ταξινομημένο δυαδικό δένδρο είναι ένα δυαδικό δένδρο στο οποίο κάθε κόμβος\nέχει στο αριστερό του υποδένδρο αριθμούς μικρότερους από τον ίδιο και στο δεξί του\nυποδένδρο αριθμούς μεγαλύτερους από τον ίδιο. Η ιδιότητα αυτή ισχύει αναδρομικά για κάθε\nυποδένδρο.\n\nΟρίστε την αναδρομική συνάρτηση:\n\n```c\nTreeptr addtree(Treeptr p, int x);\n```\n\nΗ συνάρτηση προσθέτει έναν αριθμό `x` στο ταξινομημένο δυαδικό δένδρο `p`, διατηρώντας\nτο ταξινομημένο, και επιστρέφει το νέο δένδρο. Ο αλγόριθμος λειτουργεί ως εξής:\n\n- Αν το δένδρο `p` είναι κενό (`NULL`), δημιουργείται ένας νέος κόμβος που περιέχει τον\n  αριθμό `x`.\n- Αν ο αριθμός που περιέχει ο τρέχων κόμβος είναι μεγαλύτερος από το `x`, η συνάρτηση\n  καλείται για το αριστερό παιδί του κόμβου.\n- Αν ο αριθμός είναι μικρότερος από το `x`, η συνάρτηση καλείται για το δεξί παιδί.\n- Αν ο αριθμός είναι ίσος με το `x`, δεν γίνεται εισαγωγή.\n\nΤροποποιήστε τη συνάρτηση `main` ώστε να διαβάζει αριθμούς από το πληκτρολόγιο μέχρι το\nτέλος της εισόδου και να τους προσθέτει στο δένδρο.\n\n**4.3** Κατασκευάστε την αναδρομική συνάρτηση:\n\n```c\nvoid treeprint(Treeptr p);\n```\n\nΗ συνάρτηση δέχεται ως όρισμα το δένδρο και εκτυπώνει τα περιεχόμενά του με in-order\nδιάσχιση. Ο αλγόριθμος λειτουργεί ως εξής:\n\n1. Αν το δένδρο είναι κενό (`NULL`), η συνάρτηση επιστρέφει.\n2. Διαφορετικά, εκτελούνται τα εξής βήματα:\n    - Καλείται η `treeprint` για το αριστερό παιδί.\n    - Εκτυπώνεται η τιμή του τρέχοντος κόμβου.\n    - Καλείται η `treeprint` για το δεξί παιδί.\n\nΚαλέστε τη `treeprint` από τη συνάρτηση `main` για να εκτυπώσετε το δένδρο που\nκατασκευάσατε.",
  "hint": "Το κλειδί στην `addtree` είναι ότι επιστρέφει το (πιθανώς νέο) υποδένδρο: την τιμή της\nαναδρομικής κλήσης πρέπει να την αναθέσετε πίσω στο `left` ή στο `right` του κόμβου,\nαλλιώς ο νέος κόμβος χάνεται. Νέοι κόμβοι ξεκινούν με `NULL` παιδιά. Η in-order\nδιάσχιση ταξινομημένου δένδρου τυπώνει τους αριθμούς σε αύξουσα σειρά, κάτι που σας\nδίνει έναν εύκολο έλεγχο ορθότητας."
 },
 {
  "id": "lab-lab10-bgrades",
  "kind": "lab",
  "title": "Δυαδικά αρχεία",
  "source": {
   "title": "Εργαστήριο 10, Άσκηση 2",
   "url": "https://progintro.github.io/lab-material/labs/lab10/",
   "years": [
    2025
   ]
  },
  "chapters": [
   18
  ],
  "topics": [
   "files",
   "input-output"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α18.9",
  "path": "questions/labs/lab-lab10-bgrades.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab10-bgrades.html",
  "statement": "**2.1** Κατασκευάστε το πρόγραμμα `bgrades.c`, το οποίο να ανοίγει το αρχείο `grades.dat`\nγια γράψιμο σε δυαδική μορφή. Στη συνέχεια, να διαβάζει ένα όνομα (συμβολοσειρά) από την\nπρότυπη είσοδο και έναν βαθμό και να τα γράφει στο αρχείο. Το πρόγραμμα να τερματίζει όταν\nεπισημανθεί, με κάποιο τρόπο, το τέλος της εισόδου.\n\n**2.2** Στη συνέχεια, επεκτείνετε το πρόγραμμά σας, ώστε να ανοίγει το αρχείο `grades.dat`\nγια διάβασμα, να διαβάζει τα δεδομένα που έχουν γραφεί σ' αυτό και να τα προβάλλει στην\nοθόνη.\n\n**Συναρτήσεις για Δυαδική Εισαγωγή/Εξαγωγή:**\n\n1. `size_t fread(void *ptr, size_t size, size_t count, FILE *fp)`: Διαβάζει από το ρεύμα\n   `fp` το πολύ `count` δεδομένα μεγέθους `size` το καθένα και τα αποθηκεύει στη\n   διεύθυνση `ptr`.\n2. `size_t fwrite(const void *ptr, size_t size, size_t count, FILE *fp)`: Γράφει στο\n   ρεύμα `fp` το πολύ `count` δεδομένα μεγέθους `size` το καθένα, από τη διεύθυνση `ptr`.\n\nΓια να δείτε τα περιεχόμενα του αρχείου `grades.dat`, αν δουλεύετε σ' ένα Unix σύστημα,\nχρησιμοποιήστε την εντολή `od -tu1c grades.dat` ή `hexdump -C grades.dat`.",
  "hint": "Σε δυαδικό αρχείο δεν υπάρχουν «γραμμές», οπότε το πρόγραμμα που διαβάζει πρέπει να ξέρει\nακριβώς πόσα bytes έγραψε αυτό που έγραψε: το πιο απλό είναι μια εγγραφή σταθερού\nμεγέθους (π.χ. πίνακας χαρακτήρων σταθερού μήκους για το όνομα και ένας αριθμός), που\nγράφεται και διαβάζεται ολόκληρη. Χρησιμοποιήστε τα modes με `b` και σταματήστε το\nδιάβασμα όταν η `fread` επιστρέψει λιγότερα στοιχεία από όσα ζητήσατε."
 },
 {
  "id": "lab-lab10-count",
  "kind": "lab",
  "title": "Μέτρηση στατιστικών αρχείων",
  "source": {
   "title": "Εργαστήριο 10, Άσκηση 4",
   "url": "https://progintro.github.io/lab-material/labs/lab10/",
   "years": [
    2025
   ]
  },
  "chapters": [
   18,
   12
  ],
  "topics": [
   "files",
   "command-line-args"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α18.7",
  "path": "questions/labs/lab-lab10-count.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab10-count.html",
  "statement": "Στην άσκηση αυτή θα υλοποιήσουμε ένα υποσύνολο της εντολής `wc` του Unix. Συγκεκριμένα,\nθα κατασκευάσουμε πρόγραμμα που θα μετράει το πλήθος των χαρακτήρων και το πλήθος των\nγραμμών ενός αρχείου κειμένου.\n\n**4.1** Κατασκευάστε το πρόγραμμα `count.c` που να δέχεται ως όρισμα γραμμής εντολής το\nόνομα ενός αρχείου κειμένου, να το ανοίγει για διάβασμα, να μετράει το πλήθος των\nχαρακτήρων του αρχείου και να προβάλλει το αποτέλεσμα στην οθόνη.\n\n**4.2** Τροποποιήστε το πρόγραμμά σας, ώστε να μετράει και το πλήθος των γραμμών του\nαρχείου.",
  "hint": "Διαβάστε το αρχείο χαρακτήρα-χαρακτήρα με `getc` μέχρι το `EOF`, μετρώντας κάθε\nχαρακτήρα και ξεχωριστά κάθε `'\\n'`. Συγκρίνετε τα αποτελέσματά σας με τα `wc -c` και\n`wc -l` στο ίδιο αρχείο."
 },
 {
  "id": "lab-lab10-filediff",
  "kind": "lab",
  "title": "Σύγκριση αρχείων",
  "source": {
   "title": "Εργαστήριο 10, Άσκηση 3",
   "url": "https://progintro.github.io/lab-material/labs/lab10/",
   "years": [
    2025
   ]
  },
  "chapters": [
   18,
   12
  ],
  "topics": [
   "files",
   "command-line-args"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α18.8",
  "path": "questions/labs/lab-lab10-filediff.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab10-filediff.html",
  "statement": "Δημιουργήστε το πρόγραμμα `filediff.c`, το οποίο να δέχεται στη γραμμή εντολής τα ονόματα\nδύο αρχείων και να ελέγχει αν τα αρχεία αυτά είναι ίδια byte προς byte.",
  "hint": "Ανοίξτε και τα δύο αρχεία (ελέγχοντας για `NULL`) και διαβάστε από έναν χαρακτήρα από το\nκαθένα ταυτόχρονα, μέχρι να βρείτε διαφορά ή να τελειώσουν. Μην ξεχάσετε την περίπτωση\nόπου το ένα αρχείο είναι πρόθεμα του άλλου: τα αρχεία είναι ίδια μόνο αν φτάσουν στο\n`EOF` ταυτόχρονα."
 },
 {
  "id": "lab-lab10-more-modules",
  "kind": "lab",
  "title": "Σπάστε το πρόγραμμά σας σε αρθρώματα",
  "source": {
   "title": "Εργαστήριο 10, Άσκηση 5",
   "url": "https://progintro.github.io/lab-material/labs/lab10/",
   "years": [
    2025
   ]
  },
  "chapters": [
   23,
   26,
   14
  ],
  "topics": [
   "code-organization",
   "make",
   "scope"
  ],
  "difficulty": 2,
  "type": "tooling",
  "label": "Α23.5",
  "path": "questions/labs/lab-lab10-more-modules.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab10-more-modules.html",
  "statement": "Πάρτε το πρόγραμμα `more.c` της Άσκησης 1 (προβολή ενός αρχείου κειμένου ανά 20 γραμμές)\nκαι οργανώστε το σε πολλαπλά αρχεία:\n\n**1.** Μεταφέρετε τη λογική ανάγνωσης και προβολής γραμμών σε ένα άρθρωμα `pager.c` με\nαντίστοιχο `pager.h`, αφήνοντας στη `main` μόνο τον χειρισμό των ορισμάτων γραμμής\nεντολής και το άνοιγμα του αρχείου.\n\n**2.** Βάλτε include guard στο `pager.h`.\n\n**3.** Κάντε τη σταθερά των 20 γραμμών `static` μέσα στο `pager.c`, ώστε να μην είναι\nορατή από το `main.c`.\n\n**4.** Μεταγλωττίστε πρώτα με το χέρι (`gcc -c` και σύνδεση) και μετά γράψτε ένα\n`Makefile` που κάνει το ίδιο. Επιβεβαιώστε ότι μετά από αλλαγή μόνο στο `main.c` το\n`make` ξαναμεταγλωττίζει μόνο αυτό.\n\n**5.** Προσθέστε στο `Makefile` έναν στόχο `clean`.",
  "hint": "Ακολουθήστε το παράδειγμα `collatz.h` / `collatz.c` / `main.c` του παραρτήματος του\nεργαστηρίου: στο `.h` μόνο πρωτότυπα μέσα σε `#ifndef`/`#define`/`#endif`, και\n`#include \"pager.h\"` με εισαγωγικά και στα δύο `.c`. Στο `Makefile`, κάθε `.o` πρέπει να\nεξαρτάται και από το `.h` που συμπεριλαμβάνει, και οι εντολές ξεκινούν με tab. Για τον\nέλεγχο του 4, αλλάξτε το `main.c` (ή κάντε `touch`) και ξανατρέξτε `make`."
 },
 {
  "id": "lab-lab10-more",
  "kind": "lab",
  "title": "Αρχεία κειμένου",
  "source": {
   "title": "Εργαστήριο 10, Άσκηση 1",
   "url": "https://progintro.github.io/lab-material/labs/lab10/",
   "years": [
    2025
   ]
  },
  "chapters": [
   18,
   12
  ],
  "topics": [
   "files",
   "command-line-args",
   "input-output"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α18.10",
  "path": "questions/labs/lab-lab10-more.md",
  "url": "https://progintro.github.io/study/questions/labs/lab-lab10-more.html",
  "statement": "Κατασκευάστε το πρόγραμμα `more.c` που δέχεται ως όρισμα γραμμής εντολής το όνομα ενός\nαρχείου κειμένου και προβάλλει τις γραμμές του αρχείου ανά 20, προτρέποντας τον χρήστη να\nσυνεχίσει, αν επιθυμεί, έως ότου συναντήσει το τέλος του αρχείου.\n\n**Συναρτήσεις Εισόδου/Εξόδου στην C**\n\n*Άνοιγμα και Κλείσιμο Αρχείων*\n\n```c\nFILE *fopen(const char *filename, const char *mode);\nint fclose(FILE *fp);\n```\n\n- `fopen`: Ανοίγει το αρχείο με όνομα `filename` με τρόπο προσπέλασης που καθορίζεται από\n  το `mode`. Επιστρέφει ένα ρεύμα μέσω του οποίου μπορούμε στη συνέχεια να αναφερόμαστε\n  στο αρχείο, ή `NULL` αν δεν ήταν δυνατόν να ανοίξει το αρχείο.\n    - `mode` **Παραδείγματα:**\n        - `\"r\"`: Διάβασμα από υπάρχον αρχείο.\n        - `\"w\"`: Γράψιμο σε αρχείο. Δημιουργείται αν δεν υπάρχει ή διαγράφονται τα\n          περιεχόμενα αν υπάρχει.\n        - `\"a\"`: Προσάρτηση δεδομένων στο τέλος του αρχείου.\n        - `\"r+\"`, `\"w+\"`, `\"a+\"`: Διάφοροι συνδυασμοί ανάγνωσης και εγγραφής.\n- `fclose`: Κλείνει το ρεύμα `fp`. Επιστρέφει `0` σε περίπτωση επιτυχίας.\n\n*Άλλες Συναρτήσεις*\n\n1. `int feof(FILE *fp)`: Επιστρέφει τιμή διαφορετική από το 0 αν το προηγούμενο\n   διάβασμα απέτυχε λόγω τέλους αρχείου, αλλιώς επιστρέφει 0.\n2. `int fprintf(FILE *fp, ...)`: Αντίστοιχη της `printf`, αλλά γράφει στο ρεύμα `fp` αντί\n   του `stdout`.\n3. `int fscanf(FILE *fp, ...)`: Αντίστοιχη της `scanf`, αλλά διαβάζει από το ρεύμα `fp`\n   αντί του `stdin`.\n4. `char *fgets(char *buf, int max, FILE *fp)`: Διαβάζει το πολύ `max-1` χαρακτήρες από\n   το ρεύμα `fp` μέχρι την αλλαγή γραμμής και τους φυλάσσει στο `buf`. Αν δεν υπάρχουν\n   δεδομένα, επιστρέφει `NULL`.\n5. `int getc(FILE *fp)`: Επιστρέφει τον επόμενο χαρακτήρα από το ρεύμα `fp`, ή `EOF` αν\n   φτάσει στο τέλος του αρχείου.",
  "hint": "Ελέγξτε το `argc` και την τιμή που επιστρέφει η `fopen` πριν διαβάσετε οτιδήποτε.\nΔιαβάζετε με `fgets` και μετράτε γραμμές· κάθε 20 γραμμές ρωτάτε τον χρήστη από το\n`stdin`, που είναι διαφορετικό ρεύμα από το αρχείο. Προσέξτε ότι μια γραμμή μεγαλύτερη\nαπό τον buffer σας έρχεται σε περισσότερα από ένα κομμάτια."
 },
 {
  "id": "slides-lec00-ask-question",
  "kind": "slides",
  "title": "Έχω μια ερώτηση, τι κάνω;",
  "source": {
   "title": "Διάλεξη 0: Καλημέρα Κόσμε!, διαφάνεια 16",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec00.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   0
  ],
  "topics": [
   "course-intro"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "label": "Α0.1",
  "path": "questions/slides/slides-lec00-ask-question.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec00-ask-question.html",
  "statement": "Έχω μια ερώτηση για το μάθημα, τι κάνω;\n\n- Α. Στέλνω email στον Αυγερινό/Τάκη\n- Β. Ελέγχω αν έχει απαντηθεί στο piazza και εφόσον *δεν* έχει απαντηθεί, ποστάρω καινούρια ερώτηση",
  "hint": "Σκεφτείτε πόσοι φοιτητές έχουν πιθανότατα την ίδια απορία με εσάς, και ποιος τρόπος επικοινωνίας κάνει την απάντηση διαθέσιμη σε όλους."
 },
 {
  "id": "slides-lec00-bread-and-eggs",
  "kind": "slides",
  "title": "Ψωμί και αυγά",
  "source": {
   "title": "Διάλεξη 0: Καλημέρα Κόσμε!, διαφάνεια 26",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec00.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   0
  ],
  "topics": [
   "computers"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α0.2",
  "path": "questions/slides/slides-lec00-bread-and-eggs.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec00-bread-and-eggs.html",
  "statement": "Γιατί επινοήσαμε τις γλώσσες προγραμματισμού;\n\n> Joe says to his programmer friend Charlie:\n>\n> \"Go to the store and buy a loaf of bread. If they have eggs, buy a dozen.\"\n>\n> Charlie returns with 12 loaves of bread.\n\nΕξηγήστε πώς προκύπτουν οι δύο ερμηνείες της οδηγίας. Τι είδους αμφισημία είναι αυτή (λεξιλογική ή συντακτική); Δώστε και ένα παράδειγμα του άλλου είδους.",
  "hint": "Ρωτήστε «δώδεκα από τι;». Η λεξιλογική αμφισημία αφορά μία λέξη με πολλές σημασίες, ενώ η συντακτική αφορά τον τρόπο που συνδέονται οι λέξεις μιας πρότασης."
 },
 {
  "id": "slides-lec00-hello-world",
  "kind": "slides",
  "title": "Hello World σε online compiler",
  "source": {
   "title": "Διάλεξη 0: Καλημέρα Κόσμε!, διαφάνεια 32",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec00.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   0
  ],
  "topics": [
   "compilation",
   "input-output"
  ],
  "difficulty": 1,
  "type": "tooling",
  "label": "Α0.3",
  "path": "questions/slides/slides-lec00-hello-world.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec00-hello-world.html",
  "statement": "Ας τρέξουμε το παρακάτω πρόγραμμα με έναν [online compiler](https://www.programiz.com/c-programming/online-compiler/):\n\n```c\n/* File: helloworld.c */\n#include <stdio.h>\n\nint main() {\n  printf(\"Hello world\\n\");\n}\n```\n\nΤι τυπώνει; Στη συνέχεια αλλάξτε το ώστε να τυπώνει δύο γραμμές, και δοκιμάστε τι συμβαίνει αν αφαιρέσετε το `\\n`.",
  "hint": "Κάθε κλήση της `printf` τυπώνει ακριβώς ό,τι βρίσκεται ανάμεσα στα διπλά εισαγωγικά· η αλλαγή γραμμής γίνεται μόνο όπου υπάρχει `\\n`."
 },
 {
  "id": "slides-lec00-highest-mountain",
  "kind": "slides",
  "title": "Το πιο ψηλό βουνό του κόσμου",
  "source": {
   "title": "Διάλεξη 0: Καλημέρα Κόσμε!, διαφάνεια 25",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec00.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   0
  ],
  "topics": [
   "computers"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α0.4",
  "path": "questions/slides/slides-lec00-highest-mountain.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec00-highest-mountain.html",
  "statement": "Quiz: Ποιο είναι το πιο ψηλό βουνό του κόσμου;\n\nΤι μας διδάσκει η ερώτηση αυτή για το αν μπορούμε να δίνουμε οδηγίες σε έναν υπολογιστή σε ανθρώπινη γλώσσα;",
  "hint": "Πριν απαντήσετε, ορίστε τι σημαίνει «ψηλό»: ύψος από τη στάθμη της θάλασσας, απόσταση από το κέντρο της Γης ή ύψος από τη βάση ως την κορυφή; Κάθε ορισμός δίνει άλλο βουνό."
 },
 {
  "id": "slides-lec00-pass-without-labs",
  "kind": "slides",
  "title": "Περνάω χωρίς εργασίες και εργαστήριο;",
  "source": {
   "title": "Διάλεξη 0: Καλημέρα Κόσμε!, διαφάνεια 11",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec00.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   0
  ],
  "topics": [
   "course-intro"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α0.5",
  "path": "questions/slides/slides-lec00-pass-without-labs.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec00-pass-without-labs.html",
  "statement": "Με βάση τον τρόπο βαθμολόγησης του μαθήματος:\n\n- πρωτοετείς: 50% Τελική Εξέταση + 30% Ασκήσεις + 20% Εργαστήριο·\n- αλλιώς: 70% Τελική Εξέταση + 30% Ασκήσεις·\n\nόπου οι Ασκήσεις είναι προαιρετικές: άρα μπορώ να περάσω χωρίς να κάνω εργασίες/εργαστήριο;",
  "hint": "Χωρίστε την απάντηση σε δύο μέρη: τι επιτρέπουν οι αριθμοί (θεωρητικά) και πώς προετοιμάζεται κανείς για μια γραπτή εξέταση προγραμματισμού (στην πράξη). «In theory, theory and practice are the same. In practice, they are not.»"
 },
 {
  "id": "slides-lec00-programs-you-know",
  "kind": "slides",
  "title": "Παραδείγματα προγραμμάτων",
  "source": {
   "title": "Διάλεξη 0: Καλημέρα Κόσμε!, διαφάνεια 23",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec00.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   0
  ],
  "topics": [
   "computers"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α0.6",
  "path": "questions/slides/slides-lec00-programs-you-know.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec00-programs-you-know.html",
  "statement": "Poll: Έχει κάποιο παιδί προγραμματίσει; Κάποια παραδείγματα προγραμμάτων που ξέρετε;",
  "hint": "Πρόγραμμα είναι η καταγραφή της επίλυσης ενός προβλήματος. Σκεφτείτε ποιο πρόβλημα λύνει κάθε εφαρμογή που χρησιμοποιείτε καθημερινά (στο κινητό, στον υπολογιστή, ακόμα και σε ένα πλυντήριο), ποια δεδομένα δέχεται και ποια αποτελέσματα παράγει."
 },
 {
  "id": "slides-lec00-why-programming",
  "kind": "slides",
  "title": "Γιατί προγραμματισμός το 2025;",
  "source": {
   "title": "Διάλεξη 0: Καλημέρα Κόσμε!, διαφάνεια 5",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec00.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   0
  ],
  "topics": [
   "course-intro"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α0.7",
  "path": "questions/slides/slides-lec00-why-programming.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec00-why-programming.html",
  "statement": "Γιατί να ασχοληθείς με τον προγραμματισμό το 2025; Δώστε τουλάχιστον τρεις λόγους.",
  "hint": "Σκεφτείτε σε πόσα διαφορετικά επιστημονικά πεδία και σε πόσες χώρες χρειάζεται κάποιος που γράφει κώδικα, πού βρίσκονται οι μεγάλες τεχνολογικές εξελίξεις των τελευταίων δεκαετιών, και τι είδους δουλειά είναι η επίλυση προβλημάτων."
 },
 {
  "id": "slides-lec01-architecture-examples",
  "kind": "slides",
  "title": "Παραδείγματα για κάθε επίπεδο ενός υπολογιστικού συστήματος",
  "source": {
   "title": "Διάλεξη 1: Η Γραμμή Εντολών, διαφάνεια 7",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec01.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   1
  ],
  "topics": [
   "computers"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α1.1",
  "path": "questions/slides/slides-lec01-architecture-examples.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec01-architecture-examples.html",
  "statement": "Η αρχιτεκτονική ενός υπολογιστικού συστήματος περιγράφεται από την αλυσίδα:\n\n```text\nUsers / Χρήστες --(Χρησιμοποιούν)--> Applications or Programs / Εφαρμογές ή Προγράμματα\n  --(Χρειάζονται)--> Operating System / Λειτουργικό Σύστημα --(Χρειάζεται)--> Hardware / Υλικό\n```\n\nΠαραδείγματα;",
  "hint": "Για κάθε κουτί της αλυσίδας σκεφτείτε κάτι που χρησιμοποιείτε καθημερινά: ποιες εφαρμογές ανοίγετε, σε ποιο λειτουργικό σύστημα τρέχουν και σε ποιες συσκευές."
 },
 {
  "id": "slides-lec01-echo-arguments",
  "kind": "slides",
  "title": "Πρόγραμμα και ορίσματα στο /bin/echo",
  "source": {
   "title": "Διάλεξη 1: Η Γραμμή Εντολών, διαφάνεια 15",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec01.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   1
  ],
  "topics": [
   "shell"
  ],
  "difficulty": 1,
  "type": "tooling",
  "label": "Α1.2",
  "path": "questions/slides/slides-lec01-echo-arguments.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec01-echo-arguments.html",
  "statement": "Για να τρέξουμε ένα πρόγραμμα με N ορίσματα πρέπει να γράψουμε:\n\n```text\nΠρόγραμμα(Όρισμα0)  Όρισμα1  Όρισμα2 …  ΌρισμαN\n```\n\nΠαράδειγμα:\n\n```sh\n/bin/echo hello good world\n```\n\nΠοιο είναι το πρόγραμμα; Πόσα ορίσματα έχει;",
  "hint": "Τα ορίσματα χωρίζονται με κενά. Προσέξτε τι ρόλο έχει η πρώτη λέξη της γραμμής σύμφωνα με τη γενική μορφή, και μετά τρέξτε την εντολή για να δείτε τι τυπώνει."
 },
 {
  "id": "slides-lec01-explore-coreutils",
  "kind": "slides",
  "title": "Εξερευνήστε κι άλλα βασικά προγράμματα",
  "source": {
   "title": "Διάλεξη 1: Η Γραμμή Εντολών, διαφάνεια 31",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec01.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   1
  ],
  "topics": [
   "shell",
   "unix"
  ],
  "difficulty": 2,
  "type": "tooling",
  "label": "Α1.5",
  "path": "questions/slides/slides-lec01-explore-coreutils.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec01-explore-coreutils.html",
  "statement": "Υπάρχουν και άλλα βασικά προγράμματα που δεν κοιτάξαμε (στα coreutils ή εκτός) τα οποία προτείνουμε να εξερευνήσετε:\n\n```text\nfind, grep, sort, df -h, du -sh, wc -l, file, which, basename, dirname, ping, curl\n```\n\nΓια καθένα, βρείτε τι κάνει και τρέξτε το τουλάχιστον μία φορά σε κάποιο αρχείο ή κατάλογο του λογαριασμού σας.",
  "hint": "Ξεκινήστε από το `man` κάθε εντολής (π.χ. `man wc`) και διαβάστε τις πρώτες γραμμές της περιγραφής και τις επιλογές που αναφέρει η διαφάνεια (`-h`, `-sh`, `-l`). Δοκιμάστε τις σε αρχεία που ήδη έχετε, όπως το `hello.c`."
 },
 {
  "id": "slides-lec01-try-commands",
  "kind": "slides",
  "title": "Τρέξτε μόνοι σας τις εντολές της διάλεξης",
  "source": {
   "title": "Διάλεξη 1: Η Γραμμή Εντολών, διαφάνεια 42",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec01.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   1
  ],
  "topics": [
   "shell",
   "unix",
   "compilation"
  ],
  "difficulty": 1,
  "type": "tooling",
  "label": "Α1.3",
  "path": "questions/slides/slides-lec01-try-commands.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec01-try-commands.html",
  "statement": "Εγκαταστήστε WSL και προσπαθήστε να τρέξετε τις εντολές που είπαμε μόνοι/ες σας!\n\nΣυγκεκριμένα, στη διάλεξη είδαμε:\n\n- τις εντολές `who`, `last`, `whoami`, `id`, `users`, `factor 2394872891`, `hostname`, `sleep 3`, `uptime`, `uname -a`, `top`, `man`, `ps` (διαφάνεια 25)·\n- τον χειρισμό αρχείων με `pwd`, `ls`, `ls -l`, `cat`, `mkdir`, `cd`, `cp`, `rm`, `rmdir` (διαφάνειες 29–30)·\n- τη μεταγλώττιση και εκτέλεση του Hello World με `gcc hello.c`, `./a.out`, `file a.out`, `gcc -o hello hello.c`, `./hello` (διαφάνειες 33–34), και τον κωδικό εξόδου με `echo $?` (διαφάνεια 39).",
  "hint": "Αν δεν έχετε Windows, αρκεί ένα τερματικό σε Linux ή macOS, ή σύνδεση με `ssh` στα μηχανήματα του εργαστηρίου. Συγκρίνετε την έξοδο κάθε εντολής με αυτή των διαφανειών και εξηγήστε τις διαφορές (άλλος χρήστης, άλλο μηχάνημα, άλλη ώρα). Για τις διαδραστικές εντολές, βγαίνετε με `q`."
 },
 {
  "id": "slides-lec01-why-os",
  "kind": "slides",
  "title": "Γιατί χρειαζόμαστε λειτουργικό σύστημα",
  "source": {
   "title": "Διάλεξη 1: Η Γραμμή Εντολών, διαφάνεια 9",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec01.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   1
  ],
  "topics": [
   "computers"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α1.4",
  "path": "questions/slides/slides-lec01-why-os.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec01-why-os.html",
  "statement": "Operating System: Το λογισμικό του υπολογιστή που είναι υπεύθυνο για:\n\n- Την διαχείριση του υλικού του υπολογιστή (συσκευές)\n- Την διαχείριση πόρων του συστήματος (πόση μνήμη μπορεί να χρησιμοποιηθεί από ένα πρόγραμμα, πότε θα πάρει κύκλους στον επεξεργαστή, κ.ο.κ.)\n- Προσφορά υπηρεσιών σε προγράμματα χρηστών (αποθήκευση πληροφοριών στον δίσκο, μεταφορά πληροφοριών μέσω δικτύου, κ.ο.κ.)\n\nΓιατί να μην είναι το πρόγραμμά μας υπεύθυνο για αυτά;",
  "hint": "Σκεφτείτε πόσα προγράμματα τρέχουν ταυτόχρονα στον υπολογιστή σας και ότι μοιράζονται την ίδια μνήμη, τον ίδιο επεξεργαστή και τον ίδιο δίσκο. Σκεφτείτε επίσης πόσα διαφορετικά μοντέλα συσκευών θα έπρεπε να «ξέρει» κάθε πρόγραμμα."
 },
 {
  "id": "slides-lec02-ascii-count",
  "kind": "slides",
  "title": "Πόσοι χαρακτήρες ASCII υπάρχουν",
  "source": {
   "title": "Διάλεξη 2: Μνήμη και Μεταβλητές, διαφάνεια 17",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec02.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "computers",
   "types"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α2.1",
  "path": "questions/slides/slides-lec02-ascii-count.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec02-ascii-count.html",
  "statement": "Τα 8 bits ενός `char` μπορεί να ερμηνευθούν ως χαρακτήρας κειμένου με την αντιστοίχιση του πίνακα ASCII (`man ascii`). Π.χ., ο αριθμός $67_{(10)} = 43_{(16)}$ αντιστοιχεί στο γράμμα `'C'`.\n\nΠόσους διαφορετικούς χαρακτήρες έχουμε στο σύστημα ASCII; Γιατί;",
  "hint": "Δείτε ποιος είναι ο μεγαλύτερος κωδικός στον πίνακα της `man ascii` (και στις τρεις βάσεις). Πόσα bits χρειάζονται για να γραφτεί;"
 },
 {
  "id": "slides-lec02-byte-values",
  "kind": "slides",
  "title": "Πόσα διαφορετικά bytes υπάρχουν",
  "source": {
   "title": "Διάλεξη 2: Μνήμη και Μεταβλητές, διαφάνεια 5",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec02.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "computers"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α2.2",
  "path": "questions/slides/slides-lec02-byte-values.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec02-byte-values.html",
  "statement": "Ένα byte είναι μια ομάδα από 8 bits (octet), όπως το `00101010`.\n\nΠόσα διαφορετικά 8-bit bytes μπορούμε να έχουμε;",
  "hint": "Πόσες επιλογές έχει το πρώτο bit; Και για καθεμία από αυτές, πόσες το δεύτερο; Μετρήστε πρώτα για 1, 2 και 3 bits και γενικεύστε."
 },
 {
  "id": "slides-lec02-hex-digits",
  "kind": "slides",
  "title": "Δεκαεξαδικά ψηφία ενός byte",
  "source": {
   "title": "Διάλεξη 2: Μνήμη και Μεταβλητές, διαφάνεια 10",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec02.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "computers"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α2.3",
  "path": "questions/slides/slides-lec02-hex-digits.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec02-hex-digits.html",
  "statement": "Ένας δεκαεξαδικός αριθμός εκφράζεται με μια ακολουθία από 16 σύμβολα: `0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F`. Για παράδειγμα, $2A_{(16)} = 2 \\cdot 16^1 + A \\cdot 16^0 = 42_{(10)}$.\n\nΠόσα ψηφία χρειαζόμαστε στο δεκαεξαδικό σύστημα για να εκφράσουμε ένα byte; Είναι το ίδιο με το δεκαδικό;",
  "hint": "Ποια είναι η μεγαλύτερη τιμή ενός byte, και πώς γράφεται σε κάθε βάση; Σκεφτείτε επίσης σε πόσα bits αντιστοιχεί ένα δεκαεξαδικό ψηφίο, αφού $16 = 2^4$."
 },
 {
  "id": "slides-lec02-int-size",
  "kind": "slides",
  "title": "Πόσο μεγάλος είναι ένας int",
  "source": {
   "title": "Διάλεξη 2: Μνήμη και Μεταβλητές, διαφάνεια 27",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec02.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "types",
   "integer-representation"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α2.4",
  "path": "questions/slides/slides-lec02-int-size.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec02-int-size.html",
  "statement": "Είπαμε ότι το μέγεθος ενός `int` είναι *συνήθως* 4 bytes. Υπάρχει τρόπος να είμαστε βέβαιοι;",
  "hint": "Υπάρχουν δύο τρόποι: ένας τελεστής της C που δίνει το μέγεθος ενός τύπου σε bytes, και μια βιβλιοθήκη που ορίζει ακέραιους τύπους με το πλήθος των bits στο όνομά τους."
 },
 {
  "id": "slides-lec02-int32-count",
  "kind": "slides",
  "title": "Ακέραιοι με 32 bit",
  "source": {
   "title": "Διάλεξη 2: Μνήμη και Μεταβλητές, διαφάνεια 18",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec02.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "integer-representation",
   "types"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α2.5",
  "path": "questions/slides/slides-lec02-int32-count.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec02-int32-count.html",
  "statement": "Ο τύπος `int` που αναπαριστά ακεραίους απαιτεί *συνήθως* 4 bytes από τον μεταγλωττιστή. Για παράδειγμα, το 42 αποθηκεύεται ως\n\n```text\n00000000000000000000000000101010\n```\n\n1. Πόσους διαφορετικούς ακεραίους μπορούμε να αναπαραστήσουμε με 32 bit;\n2. Υπάρχει κάποιο πιθανό πρόβλημα με αυτήν την αναπαράσταση;",
  "hint": "Για το (1) εφαρμόστε τον ίδιο κανόνα με το πλήθος των διαφορετικών bytes. Για το (2) σκεφτείτε δύο πράγματα: είναι αυτό το πλήθος αρκετό για κάθε πρόγραμμα, και πού «χωράει» το πρόσημο ενός αρνητικού αριθμού;"
 },
 {
  "id": "slides-lec02-man",
  "kind": "slides",
  "title": "Η εντολή για να μάθουμε για ένα πρόγραμμα",
  "source": {
   "title": "Διάλεξη 2: Μνήμη και Μεταβλητές, διαφάνεια 16",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec02.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "shell",
   "computers"
  ],
  "difficulty": 1,
  "type": "tooling",
  "label": "Α2.6",
  "path": "questions/slides/slides-lec02-man.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec02-man.html",
  "statement": "Ποια εντολή του Linux μας επιτρέπει να μάθουμε για ένα πρόγραμμα στο σύστημά μας;\n\nΧρησιμοποιήστε την για να βρείτε τον κωδικό ASCII του γράμματος `C` σε δεκαδικό και σε δεκαεξαδικό.",
  "hint": "Η εντολή εμφανίζει το εγχειρίδιο (manual) του συστήματος, και έχει σελίδες όχι μόνο για προγράμματα αλλά και για θέματα όπως ο πίνακας ASCII."
 },
 {
  "id": "slides-lec02-overflow",
  "kind": "slides",
  "title": "Υπερχείλιση ακεραίων",
  "source": {
   "title": "Διάλεξη 2: Μνήμη και Μεταβλητές, διαφάνεια 26",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec02.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "integer-representation",
   "types",
   "input-output"
  ],
  "difficulty": 2,
  "type": "debug",
  "label": "Α2.8",
  "path": "questions/slides/slides-lec02-overflow.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec02-overflow.html",
  "statement": "Τι θα τυπώσει το παρακάτω πρόγραμμα;\n\n```c\n#include <stdio.h>\n\nint main() {\n  printf(\"%d\\n\", 2000000000 + 2000000000);\n  return 0;\n}\n```\n\n```text\n$ ./overflow\n-294967296\n```\n\nΤι συνέβη; Πώς το διορθώνουμε;",
  "hint": "Ποιος είναι ο τύπος των δύο σταθερών, και ποια η μεγαλύτερη τιμή που χωράει σε αυτόν; Συγκρίνετε το $4.000.000.000$ με το $2^{32}$. Για τη διόρθωση, χρειάζεστε έναν τύπο με περισσότερα bits, τόσο για τις σταθερές όσο και στο προσδιοριστικό της `printf`."
 },
 {
  "id": "slides-lec02-twos-complement",
  "kind": "slides",
  "title": "Αρνητικοί αριθμοί σε συμπλήρωμα ως προς 2",
  "source": {
   "title": "Διάλεξη 2: Μνήμη και Μεταβλητές, διαφάνεια 21",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec02.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   2
  ],
  "topics": [
   "integer-representation"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α2.7",
  "path": "questions/slides/slides-lec02-twos-complement.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec02-twos-complement.html",
  "statement": "Υπάρχουν θετικοί και αρνητικοί ακέραιοι. Πώς αναπαριστούμε το γεγονός ότι ένας αριθμός είναι αρνητικός στη δυαδική αναπαράσταση; Τι κάνουμε με το πρόσημο;\n\nΣτο συμπλήρωμα ως προς 2 (two's complement) το πρόσημο φαίνεται από το σημαντικότερο bit του αριθμού ($0 \\to +$, $1 \\to -$). Για να πάρουμε την αναπαράσταση του $-N$ από έναν θετικό δυαδικό αριθμό $N$:\n\n1. Αντιστρέφουμε (flip) όλα τα bit του $N$.\n2. Προσθέτουμε 1.\n\nΈστω $N = 11_{(10)} = 00001011_{(2)}$. Ποια είναι η αναπαράσταση του $-N$ σε 8 bits; Επαληθεύστε ότι $N + (-N) = 0$.",
  "hint": "Κάντε τα δύο βήματα ένα-ένα, προσέχοντας τα κρατούμενα στην πρόσθεση. Στην επαλήθευση, το άθροισμα βγαίνει 9 bits· τι γίνεται με το bit που δεν χωράει στα 8;"
 },
 {
  "id": "slides-lec03-function-call",
  "kind": "slides",
  "title": "Τιμή μετά από κλήση συνάρτησης",
  "source": {
   "title": "Διάλεξη 3: Συναρτήσεις, διαφάνεια 37",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec03.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   3
  ],
  "topics": [
   "functions"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α3.1",
  "path": "questions/slides/slides-lec03-function-call.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec03-function-call.html",
  "statement": "Ποια η τιμή του `x` μετά την εκτέλεση της ανάθεσης στη `main`;\n\n```c\nint g(int x, int y, int z) {\n  return x * x + y * y + z * z + 42;\n}\n\nint main(int argc, char **argv) {\n  ....\n  int x = g(1, 2, 3);\n  ....\n}\n```",
  "hint": "Κατά την κλήση, οι παράμετροι `x`, `y`, `z` της `g` παίρνουν με τη σειρά τις τιμές των\nορισμάτων. Αντικαταστήστε τις στην παράσταση του `return`."
 },
 {
  "id": "slides-lec03-int-size",
  "kind": "slides",
  "title": "Πόσα bytes είναι ένας int;",
  "source": {
   "title": "Διάλεξη 3: Συναρτήσεις, διαφάνεια 9",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec03.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   3
  ],
  "topics": [
   "types"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α3.2",
  "path": "questions/slides/slides-lec03-int-size.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec03-int-size.html",
  "statement": "Είπαμε ότι το μέγεθος ενός `int` είναι συνήθως 4 bytes. Υπάρχει τρόπος να είμαστε\nβέβαιοι;",
  "hint": "Υπάρχουν δύο δρόμοι: ένας τελεστής της C που μετράει το μέγεθος ενός τύπου σε bytes,\nκαι μια βιβλιοθήκη που ορίζει ακέραιους τύπους με το πλήθος των bits στο όνομά τους."
 },
 {
  "id": "slides-lec03-leibniz-pi",
  "kind": "slides",
  "title": "Προσέγγιση του π με τη σειρά Leibniz",
  "source": {
   "title": "Διάλεξη 3: Συναρτήσεις, διαφάνεια 43",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec03.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   3,
   6
  ],
  "topics": [
   "floating-point",
   "loops",
   "math-algorithms"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α3.5",
  "path": "questions/slides/slides-lec03-leibniz-pi.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec03-leibniz-pi.html",
  "statement": "Challenge #2: Ο Leibniz έδειξε ότι μπορούμε να προσεγγίσουμε την τιμή του π με την\nακόλουθη φόρμουλα:\n\n$$\\frac{\\pi}{4} = \\sum_{i=0}^{\\infty} \\frac{(-1)^i}{2i+1} = \\frac{1}{1} - \\frac{1}{3} + \\frac{1}{5} - \\frac{1}{7} + \\cdots$$\n\nΘέλουμε να γράψουμε ένα πρόγραμμα που να προσεγγίζει το π. Μπορούμε;",
  "hint": "Αθροίστε ένα μεγάλο αλλά πεπερασμένο πλήθος όρων (π.χ. 100000) σε μεταβλητή `double`.\nΔεν χρειάζεται να υψώνετε το $-1$ σε δύναμη: κρατήστε τον αριθμητή και τον παρονομαστή\nτου τρέχοντος όρου σε μεταβλητές και ενημερώνετε τις σε κάθε επανάληψη. Μην ξεχάσετε\nτον πολλαπλασιασμό με 4 στο τέλος."
 },
 {
  "id": "slides-lec03-overflow",
  "kind": "slides",
  "title": "Υπερχείλιση ακεραίων",
  "source": {
   "title": "Διάλεξη 3: Συναρτήσεις, διαφάνεια 8",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec03.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   3
  ],
  "topics": [
   "integer-representation",
   "types",
   "input-output"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α3.6",
  "path": "questions/slides/slides-lec03-overflow.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec03-overflow.html",
  "statement": "Τι θα τυπώσει το παρακάτω πρόγραμμα;\n\n```c\n#include <stdio.h>\n\nint main() {\n  printf(\"%d\\n\", 2000000000 + 2000000000);\n  return 0;\n}\n```\n\nΌταν το τρέχουμε, τυπώνει:\n\n```text\n$ ./overflow\n-294967296\n```\n\nΤι συνέβη; Πώς το διορθώνουμε;",
  "hint": "Ποιος είναι ο τύπος των δύο σταθερών, άρα και του αθροίσματος, και ποια είναι η\nμέγιστη τιμή του; Συγκρίνετε το σωστό άθροισμα με το $2^{32}$. Για τη διόρθωση,\nσκεφτείτε έναν τύπο με μεγαλύτερο εύρος, το suffix των σταθερών και το προσδιοριστικό\nτης `printf` που του αντιστοιχεί."
 },
 {
  "id": "slides-lec03-power-outage",
  "kind": "slides",
  "title": "Διακοπή ρεύματος και μνήμη",
  "source": {
   "title": "Διάλεξη 3: Συναρτήσεις, διαφάνεια 3",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec03.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   3,
   2
  ],
  "topics": [
   "computers",
   "memory-model"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "label": "Α3.3",
  "path": "questions/slides/slides-lec03-power-outage.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec03-power-outage.html",
  "statement": "(Ερώτηση επανάληψης Kahoot από την προηγούμενη διάλεξη.)\n\nΜόλις έπεσε το ρεύμα, τα δεδομένα σου διατηρήθηκαν μόνο αν τα έσωσες στην:\n\n- A. Κύρια μνήμη\n- B. Δευτερεύουσα μνήμη",
  "hint": "Σκεφτείτε ποια από τις δύο μνήμες είναι πτητική, δηλαδή χάνει το περιεχόμενό της όταν\nσταματήσει η τροφοδοσία, και σε ποια ανήκει ένας σκληρός δίσκος."
 },
 {
  "id": "slides-lec03-pyth",
  "kind": "slides",
  "title": "Πυθαγόρειο θεώρημα (pyth.c)",
  "source": {
   "title": "Διάλεξη 3: Συναρτήσεις, διαφάνεια 40",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec03.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   3
  ],
  "topics": [
   "functions",
   "floating-point",
   "compilation"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α3.4",
  "path": "questions/slides/slides-lec03-pyth.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec03-pyth.html",
  "statement": "Challenge #1: Χρειαζόμαστε ένα πρόγραμμα `pyth.c` το οποίο **με δεδομένα τα μήκη των\nκαθέτων πλευρών ενός ορθογωνίου τριγώνου** να τυπώνει τα ακόλουθα:\n\n1. Το εμβαδόν του τριγώνου.\n2. Την περίμετρο του τριγώνου.",
  "hint": "Γράψτε μία συνάρτηση για κάθε υπολογισμό, με δύο ορίσματα `double`. Για την περίμετρο\nχρειάζεστε πρώτα την υποτείνουσα από το Πυθαγόρειο θεώρημα, με την `sqrt` του\n`math.h`· θυμηθείτε τι χρειάζεται στη γραμμή του `gcc` για να συνδεθεί η μαθηματική\nβιβλιοθήκη."
 },
 {
  "id": "slides-lec04-cafebeef",
  "kind": "slides",
  "title": "Η τιμή του 0xbeef | 0xcafe0000",
  "source": {
   "title": "Διάλεξη 4: Git και Τελεστές, διαφάνεια 30",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec04.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   4
  ],
  "topics": [
   "bitwise"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "label": "Α4.1",
  "path": "questions/slides/slides-lec04-cafebeef.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec04-cafebeef.html",
  "statement": "Ποια η τιμή της παράστασης `0xbeef | 0xcafe0000`;\n\n- A. `0xffffffff`\n- B. `0xcafebeef`\n- C. `0xbeefcafe`\n- D. `0xfaceb00c`",
  "hint": "Γράψτε και τους δύο αριθμούς με 8 δεκαεξαδικά ψηφία (συμπληρώνοντας μηδενικά αριστερά)\nτον έναν κάτω από τον άλλο. Κάθε δεκαεξαδικό ψηφίο είναι 4 bit, και `0 | x` είναι `x`."
 },
 {
  "id": "slides-lec04-cast-division",
  "kind": "slides",
  "title": "Τι επιστρέφει το (double)3/4;",
  "source": {
   "title": "Διάλεξη 4: Git και Τελεστές, διαφάνεια 32",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec04.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   4
  ],
  "topics": [
   "operators",
   "types",
   "precedence"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α4.10",
  "path": "questions/slides/slides-lec04-cast-division.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec04-cast-division.html",
  "statement": "Ο τελεστής μετατροπής αλλάζει τον τύπο ενός τελεστέου. Γενική μορφή: `(τύπος)τελεστέος`.\n\nΠαραδείγματα:\n\n- `(int)42.67` επιστρέφει `42`\n- `(char)67.8` επιστρέφει `'C'`\n- `(double)3` επιστρέφει `3.0`\n- `(double)3/4` επιστρέφει ??",
  "hint": "Βρείτε στον πίνακα προτεραιότητας ποιος εφαρμόζεται πρώτα, το cast ή η διαίρεση. Μετά\nσκεφτείτε τι τύπου είναι οι δύο τελεστέοι της διαίρεσης και τι κάνει η σιωπηρή\nμετατροπή τύπων. Συγκρίνετε με το `(double)(3/4)`."
 },
 {
  "id": "slides-lec04-git-cycle",
  "kind": "slides",
  "title": "Ο κύκλος clone, add, commit, push, pull",
  "source": {
   "title": "Διάλεξη 4: Git και Τελεστές, διαφάνειες 15-18",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec04.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   4
  ],
  "topics": [
   "git"
  ],
  "difficulty": 1,
  "type": "tooling",
  "label": "Α4.2",
  "path": "questions/slides/slides-lec04-git-cycle.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec04-git-cycle.html",
  "statement": "Στο repository μιας εργασίας σας (π.χ. `git@github.com:progintro/hw0-barbouni-2005.git`):\n\n1. Κάντε `git clone` το repository. Ελέγξτε τον φάκελο: τι αρχείο έχει; Τρέξτε\n   `git status` μέσα στον φάκελο: υπάρχουν αλλαγές;\n2. Δημιουργήστε ένα καινούργιο αρχείο, π.χ. `touch command/solution.txt`. Τρέξτε\n   `git status`: πώς καταγράφεται το νέο αρχείο;\n3. Προσθέστε το με `git add command/solution.txt` και τρέξτε ξανά `git status`.\n4. Τρέξτε `git commit` και δώστε ένα μήνυμα που περιγράφει την αλλαγή σας. Τρέξτε\n   `git status` και πάλι.\n5. Τρέξτε `git push` και ελέγξτε ότι οι αλλαγές σας εμφανίζονται στο GitHub!\n6. Κάντε κάποιες αλλαγές στο repository από το GitHub UI και μετά τρέξτε `git pull`.\n\nΤα βήματα προϋποθέτουν ότι έχετε φτιάξει ένα κλειδί για τον GitHub λογαριασμό σας και\nέχετε τελειώσει το configuration όπως περιγράφεται στο Φυλλάδιο 1 του εργαστηρίου.",
  "hint": "Μετά από κάθε βήμα, διαβάστε προσεκτικά τι λέει το `git status`: untracked, έτοιμο για\ncommit, ή «ahead» του server. Αν το `clone` ή το `push` αποτυγχάνει με\n`Permission denied (publickey)`, ελέγξτε το κλειδί SSH (Εργαστήριο 1, Βήμα 6)."
 },
 {
  "id": "slides-lec04-grade-adjustment",
  "kind": "slides",
  "title": "Κανόνας αναπροσαρμογής βαθμού ασκήσεων",
  "source": {
   "title": "Διάλεξη 4: Git και Τελεστές, διαφάνεια 8",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec04.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   4
  ],
  "topics": [
   "operators"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α4.3",
  "path": "questions/slides/slides-lec04-grade-adjustment.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec04-grade-adjustment.html",
  "statement": "Στο πρόγραμμα υπολογισμού βαθμολογίας (50% Τελική Εξέταση + 30% Ασκήσεις + 20%\nΕργαστήριο) προστίθεται ένας κανόνας:\n\nΚανόνας Αναπροσαρμογής: Αν ο βαθμός από τις Ασκήσεις είναι πάνω από 3 μονάδες\nμεγαλύτερος του βαθμού από την Τελική Εξέταση, τότε ο βαθμός για τις Ασκήσεις\nαναπροσαρμόζεται σε Τελική Εξέταση + 3. Πως θα το εκφράσουμε;",
  "hint": "Γράψτε πρώτα τη συνθήκη ως σύγκριση ανάμεσα σε `homework` και `final_exam + 3`. Ένας\nτελεστής της διάλεξης επιλέγει ανάμεσα σε δύο τιμές ανάλογα με μια συνθήκη, και το\nαποτέλεσμά του μπορεί να ανατεθεί ξανά στο `homework` πριν από τον υπολογισμό."
 },
 {
  "id": "slides-lec04-grade-program",
  "kind": "slides",
  "title": "Υπολογισμός βαθμολογίας πρωτοετών",
  "source": {
   "title": "Διάλεξη 4: Git και Τελεστές, διαφάνεια 8",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec04.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   4,
   3
  ],
  "topics": [
   "operators",
   "functions",
   "command-line-args"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α4.4",
  "path": "questions/slides/slides-lec04-grade-program.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec04-grade-program.html",
  "statement": "Ο βαθμός των πρωτοετών υπολογίζεται ως:\n\n50% * Τελική Εξέταση + 30% * Ασκήσεις + 20% * Εργαστήριο\n\nΈστω ότι χρησιμοποιούμε 3 ακεραίους για να αναπαραστήσουμε τα αποτελέσματα [0 - 100]:\n`int final_exam`, `int homework`, `int lab`.\n\nΣτα μαθηματικά:\n\ngrade(final_exam, homework, lab) = final_exam x 50% + homework x 30% + lab x 20%\n\nΈλεγχος ορθότητας: `grade(70, 80, 100) == 79`?\n\nΣε C; Γράψτε μια συνάρτηση `grade` και ένα πρόγραμμα που παίρνει τους τρεις βαθμούς\nως ορίσματα της γραμμής εντολών και τυπώνει τον τελικό βαθμό:\n\n```text\n$ ./grade 70 80 100\nMy grade is: 79\n```",
  "hint": "Τα ορίσματα φτάνουν στη `main` ως κείμενο μέσω των `argc`/`argv`· ελέγξτε πρώτα ότι\nείναι τρία και μετατρέψτε τα σε ακεραίους με μια συνάρτηση του `stdlib.h`. Με\nακεραίους, προσέξτε με ποια σειρά γίνονται ο πολλαπλασιασμός και η διαίρεση με το 100."
 },
 {
  "id": "slides-lec04-max-conditional",
  "kind": "slides",
  "title": "Συνάρτηση max με τον τελεστή συνθήκης",
  "source": {
   "title": "Διάλεξη 4: Git και Τελεστές, διαφάνεια 31",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec04.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   4,
   3
  ],
  "topics": [
   "operators",
   "functions"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α4.5",
  "path": "questions/slides/slides-lec04-max-conditional.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec04-max-conditional.html",
  "statement": "Ο τελεστής συνθήκης ελέγχει την συνθήκη και αν είναι αληθής επιστρέφει την πρώτη τιμή,\nαλλιώς επιστρέφει την δεύτερη. Γενική μορφή:\n\n```text\nσυνθήκη ? τιμή1 : τιμή2\n```\n\nΓια παράδειγμα, `(42 > 0) ? 8 : 16` επιστρέφει `8` και `(42 == 0) ? 8 : 16`\nεπιστρέφει `16`.\n\nΤι τύπου είναι ο τελεστής συνθήκης; Πως θα φτιάχναμε μια συνάρτηση `max`;",
  "hint": "Μετρήστε τους τελεστέους του. Επειδή ο τελεστής επιστρέφει τιμή, η συνάρτηση `max` δύο\nακεραίων μπορεί να αποτελείται από μία μόνο εντολή `return`."
 },
 {
  "id": "slides-lec04-msb",
  "kind": "slides",
  "title": "Απομόνωση του πιο σημαντικού bit",
  "source": {
   "title": "Διάλεξη 4: Git και Τελεστές, διαφάνεια 29",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec04.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   4
  ],
  "topics": [
   "bitwise"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "label": "Α4.6",
  "path": "questions/slides/slides-lec04-msb.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec04-msb.html",
  "statement": "Πως απομονώνουμε το πιο σημαντικό bit σε ένα byte;\n\n- A. `byte & 0xFF`\n- B. `byte & 0x80`\n- C. `byte | 0xFF`\n- D. `byte | 0x80`",
  "hint": "Γράψτε τις σταθερές `0xFF` και `0x80` σε δυαδικό. «Απομονώνω» σημαίνει ότι όλα τα\nάλλα bit γίνονται 0 και μένει μόνο το bit που θέλουμε: ποιος τελεστής, `&` ή `|`,\nμπορεί να μηδενίσει bit;"
 },
 {
  "id": "slides-lec04-operator-arity",
  "kind": "slides",
  "title": "Τι τύπου τελεστές είναι;",
  "source": {
   "title": "Διάλεξη 4: Git και Τελεστές, διαφάνειες 25-28 και 31",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec04.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   4
  ],
  "topics": [
   "operators",
   "bitwise"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α4.7",
  "path": "questions/slides/slides-lec04-operator-arity.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec04-operator-arity.html",
  "statement": "Με βάση το arity (πόσους τελεστέους έχουν) οι τελεστές είναι μοναδιαίοι (unary),\nδυαδικοί (binary) ή τριαδικοί (ternary). Σε ποια κατηγορία εντάσσονται:\n\n1. οι αριθμητικοί τελεστές `+`, `-`, `*`, `/`, `%`;\n2. οι συγκριτικοί τελεστές `==`, `!=`, `>`, `<`, `>=`, `<=`;\n3. οι λογικοί τελεστές `&&`, `||`, `!`;\n4. οι bitwise τελεστές `&`, `|`, `^`, `~`, `<<`, `>>`;\n5. ο τελεστής συνθήκης `συνθήκη ? τιμή1 : τιμή2`;",
  "hint": "Μετρήστε πόσους τελεστέους χρειάζεται κάθε τελεστής σε ένα παράδειγμα χρήσης του.\nΠροσέξτε ότι σε δύο από τις ομάδες υπάρχει ένας τελεστής που διαφέρει από τους\nυπόλοιπους της ομάδας."
 },
 {
  "id": "slides-lec04-operators-as-functions",
  "kind": "slides",
  "title": "Τελεστές ως συναρτήσεις",
  "source": {
   "title": "Διάλεξη 4: Git και Τελεστές, διαφάνειες 21 και 25",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec04.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   4,
   3
  ],
  "topics": [
   "operators",
   "functions"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α4.8",
  "path": "questions/slides/slides-lec04-operators-as-functions.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec04-operators-as-functions.html",
  "statement": "Στην παράσταση `x + 42` η μεταβλητή `x` είναι ο 1ος τελεστέος (operand), η σταθερά\n`42` ο 2ος, και το `+` ο τελεστής (operator) για πρόσθεση.\n\n1. Μας θυμίζει κάτι ο τελεστής και οι τελεστέοι;\n2. Τι τύπο θα είχαν οι αριθμητικοί τελεστές (`+`, `-`, `*`, `/`, `%`) αν ήταν\n   συναρτήσεις;",
  "hint": "Σκεφτείτε τι παίρνει και τι επιστρέφει μια συνάρτηση. Για το δεύτερο, γράψτε το\nπρωτότυπο μιας συνάρτησης `plus` για ακεραίους και μετά για πραγματικούς· τι σας λέει\nαυτό για το `85 / 2` και το `85.0 / 2.0`;"
 },
 {
  "id": "slides-lec04-precedence",
  "kind": "slides",
  "title": "Προτεραιότητα και προσεταιριστικότητα",
  "source": {
   "title": "Διάλεξη 4: Git και Τελεστές, διαφάνεια 39",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec04.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   4
  ],
  "topics": [
   "precedence",
   "operators"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α4.9",
  "path": "questions/slides/slides-lec04-precedence.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec04-precedence.html",
  "statement": "Η προτεραιότητα ενός τελεστή καθορίζει την σειρά με την οποία θα εκτελεστούν οι\nυπολογισμοί. Για παράδειγμα, ο πολλαπλασιασμός έχει υψηλότερη προτεραιότητα από την\nπρόσθεση:\n\n```text\n5 * 6 + 3 * 4 επιστρέφει ??\n```\n\nΑν δύο τελεστές έχουν την ίδια προτεραιότητα, η προσεταιριστικότητα τους καθορίζει την\nσειρά των υπολογισμών (αριστερά προς τα δεξιά ή το αντίστροφο). Για παράδειγμα, ο\nπολλαπλασιασμός και η διαίρεση έχουν την ίδια προτεραιότητα, ενώ η προσεταιριστικότητα\nτους είναι από αριστερά προς τα δεξιά:\n\n```text\n90 * 50 / 100 επιστρέφει ??\n```",
  "hint": "Βάλτε παρενθέσεις σύμφωνα με τους δύο κανόνες και υπολογίστε από μέσα προς τα έξω. Για\nτο δεύτερο, σκεφτείτε αν θα άλλαζε το αποτέλεσμα (με ακεραίους) αν η σειρά ήταν από\nδεξιά προς τα αριστερά."
 },
 {
  "id": "slides-lec05-bitwise-or-hex",
  "kind": "slides",
  "title": "Η τιμή της 0xbeef | 0xcafe0000",
  "source": {
   "title": "Διάλεξη 5: Τελεστές και Εντολές, διαφάνεια 12",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec05.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   5
  ],
  "topics": [
   "bitwise"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "label": "Α5.1",
  "path": "questions/slides/slides-lec05-bitwise-or-hex.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec05-bitwise-or-hex.html",
  "statement": "Ποια η τιμή της παράστασης `0xbeef | 0xcafe0000`;\n\n- A. `0xffffffff`\n- B. `0xcafebeef`\n- C. `0xbeefcafe`\n- D. `0xfaceb00c`",
  "hint": "Γράψτε και τους δύο αριθμούς με 8 δεκαεξαδικά ψηφία, τον έναν κάτω από τον άλλον.\nΤι δίνει το `x | 0` σε κάθε θέση;"
 },
 {
  "id": "slides-lec05-cast-division",
  "kind": "slides",
  "title": "Cast και διαίρεση: (double)3/4",
  "source": {
   "title": "Διάλεξη 5: Τελεστές και Εντολές, διαφάνεια 14",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec05.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   5
  ],
  "topics": [
   "operators",
   "types",
   "precedence"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α5.2",
  "path": "questions/slides/slides-lec05-cast-division.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec05-cast-division.html",
  "statement": "Ο τελεστής μετατροπής αλλάζει τον τύπο ενός τελεστέου, με γενική μορφή\n`(τύπος)τελεστέος`. Για παράδειγμα:\n\n```text\n(int)42.67   επιστρέφει 42\n(char)67.8   επιστρέφει 'C'\n(double)3    επιστρέφει 3.0\n(double)3/4  επιστρέφει ??\n```\n\nΤι επιστρέφει το `(double)3/4`;",
  "hint": "Αποφασίστε πρώτα τι εφαρμόζεται πρώτο, το cast ή η διαίρεση (δείτε τον πίνακα\nπροτεραιότητας). Μετά σκεφτείτε τι γίνεται σε μια διαίρεση όπου ο ένας τελεστέος είναι\n`double` και ο άλλος `int`. Συγκρίνετε με το `(double)(3/4)`."
 },
 {
  "id": "slides-lec05-msb",
  "kind": "slides",
  "title": "Απομόνωση του πιο σημαντικού bit",
  "source": {
   "title": "Διάλεξη 5: Τελεστές και Εντολές, διαφάνεια 11",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec05.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   5
  ],
  "topics": [
   "bitwise"
  ],
  "difficulty": 1,
  "type": "multiple-choice",
  "label": "Α5.3",
  "path": "questions/slides/slides-lec05-msb.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec05-msb.html",
  "statement": "Πώς απομονώνουμε το πιο σημαντικό bit σε ένα byte;\n\n- A. `byte & 0xFF`\n- B. `byte & 0x80`\n- C. `byte | 0xFF`\n- D. `byte | 0x80`",
  "hint": "Γράψτε τα `0xFF` και `0x80` στο δυαδικό. Ποιος τελεστής μηδενίζει τα bit που δεν σας\nενδιαφέρουν και ποιος τα κάνει `1`;"
 },
 {
  "id": "slides-lec05-operator-arity",
  "kind": "slides",
  "title": "Τι τύπου τελεστές είναι;",
  "source": {
   "title": "Διάλεξη 5: Τελεστές και Εντολές, διαφάνειες 7-10, 13",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec05.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   5
  ],
  "topics": [
   "operators",
   "bitwise"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α5.4",
  "path": "questions/slides/slides-lec05-operator-arity.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec05-operator-arity.html",
  "statement": "Οι τελεστές χωρίζονται σε μοναδιαίους (unary), δυαδικούς (binary) και τριαδικούς\n(ternary). Σε ποια κατηγορία ανήκουν:\n\n1. οι αριθμητικοί τελεστές `+`, `-`, `*`, `/`, `%`;\n2. οι συγκριτικοί τελεστές `==`, `!=`, `>`, `<`, `>=`, `<=`;\n3. οι λογικοί τελεστές `&&`, `||`, `!`;\n4. οι bitwise τελεστές `&`, `|`, `^`, `~`, `<<`, `>>`;\n5. ο τελεστής συνθήκης `συνθήκη ? τιμή1 : τιμή2`;",
  "hint": "Μετρήστε πόσους τελεστέους παίρνει ο καθένας στα παραδείγματα των πινάκων (π.χ.\n`42 > 0 && 2 > 3`, `!(42 < 0)`, `~0xF0`). Προσέξτε ότι μέσα στην ίδια οικογένεια\nμπορεί να υπάρχουν τελεστές διαφορετικής κατηγορίας."
 },
 {
  "id": "slides-lec05-operator-as-function",
  "kind": "slides",
  "title": "Οι αριθμητικοί τελεστές ως συναρτήσεις",
  "source": {
   "title": "Διάλεξη 5: Τελεστές και Εντολές, διαφάνεια 7",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec05.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   5
  ],
  "topics": [
   "operators",
   "functions",
   "types"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α5.5",
  "path": "questions/slides/slides-lec05-operator-as-function.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec05-operator-as-function.html",
  "statement": "Δίνεται ο πίνακας των αριθμητικών τελεστών:\n\n| Τελεστής | Ερμηνεία | Παραδείγματα |\n| --- | --- | --- |\n| `+` | πρόσθεση | `40 + 2` επιστρέφει `42`, `40.0 + 2.0` επιστρέφει `42.0` |\n| `-` | αφαίρεση | `44 - 2` επιστρέφει `42`, `44.0 - 2.0` επιστρέφει `42.0` |\n| `*` | πολλαπλασιασμός | `42 * 2` επιστρέφει `84`, `42.0 * 2.0` επιστρέφει `84.0` |\n| `/` | διαίρεση | `85.0 / 2.0` επιστρέφει `42.5`, `85 / 2` επιστρέφει `42` |\n| `%` | υπόλοιπο | `7 % 2` επιστρέφει `1` |\n\nΤι τύπο θα είχαν οι τελεστές αν ήταν συναρτήσεις;",
  "hint": "Γράψτε την επικεφαλίδα (πρωτότυπο) μιας συνάρτησης `add` που κάνει ό,τι το `40 + 2`:\nπόσα ορίσματα παίρνει, τι τύπου, και τι επιστρέφει; Μετά σκεφτείτε τι αλλάζει για το\n`40.0 + 2.0` και γιατί το `85 / 2` δίνει `42`."
 },
 {
  "id": "slides-lec05-precedence",
  "kind": "slides",
  "title": "Προτεραιότητα και προσεταιριστικότητα",
  "source": {
   "title": "Διάλεξη 5: Τελεστές και Εντολές, διαφάνεια 21",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec05.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   5
  ],
  "topics": [
   "precedence",
   "operators"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α5.6",
  "path": "questions/slides/slides-lec05-precedence.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec05-precedence.html",
  "statement": "Η προτεραιότητα ενός τελεστή καθορίζει την σειρά με την οποία θα εκτελεστούν οι\nυπολογισμοί. Για παράδειγμα, ο πολλαπλασιασμός έχει υψηλότερη προτεραιότητα από την\nπρόσθεση:\n\n```c\n5 * 6 + 3 * 4    // επιστρέφει ??\n```\n\nΑν δύο τελεστές έχουν την ίδια προτεραιότητα, η προσεταιριστικότητα τους καθορίζει την\nσειρά των υπολογισμών (αριστερά προς τα δεξιά ή το αντίστροφο). Για παράδειγμα, ο\nπολλαπλασιασμός και η διαίρεση έχουν την ίδια προτεραιότητα, ενώ η\nπροσεταιριστικότητα τους είναι από αριστερά προς τα δεξιά:\n\n```c\n90 * 50 / 100    // επιστρέφει ??\n```\n\nΤι επιστρέφει η κάθε έκφραση (οι αριθμοί είναι `int`);",
  "hint": "Βάλτε παρενθέσεις εκεί όπου τις βάζει ο μεταγλωττιστής και υπολογίστε από μέσα προς\nτα έξω. Στη δεύτερη, σκεφτείτε τι θα βγαίνει αν η διαίρεση γινόταν πρώτη, με ακέραια\nδιαίρεση."
 },
 {
  "id": "slides-lec05-ternary-max",
  "kind": "slides",
  "title": "Συνάρτηση max με τον τελεστή συνθήκης",
  "source": {
   "title": "Διάλεξη 5: Τελεστές και Εντολές, διαφάνεια 13",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec05.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   5,
   3
  ],
  "topics": [
   "operators",
   "functions"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α5.7",
  "path": "questions/slides/slides-lec05-ternary-max.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec05-ternary-max.html",
  "statement": "Ο τελεστής συνθήκης ελέγχει την συνθήκη και αν είναι αληθής επιστρέφει την πρώτη\nτιμή, αλλιώς επιστρέφει την δεύτερη. Γενική μορφή:\n\n```text\nσυνθήκη ? τιμή1 : τιμή2\n```\n\nΓια παράδειγμα, `(42 > 0) ? 8 : 16` επιστρέφει `8` και `(42 == 0) ? 8 : 16`\nεπιστρέφει `16`.\n\nΤι τύπου είναι ο τελεστής συνθήκης; Πώς θα φτιάχναμε μια συνάρτηση `max`;",
  "hint": "Μετρήστε τους τελεστέους του. Για τη `max`: η συνάρτηση παίρνει δύο ακεραίους και\nολόκληρο το σώμα της μπορεί να είναι ένα `return` με μια έκφραση συνθήκης."
 },
 {
  "id": "slides-lec06-dangling-else",
  "kind": "slides",
  "title": "Το πρόβλημα του dangling else",
  "source": {
   "title": "Διάλεξη 6: Εντολές και Ροή Ελέγχου, διαφάνεια 15",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec06.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   6
  ],
  "topics": [
   "conditionals"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α6.8",
  "path": "questions/slides/slides-lec06-dangling-else.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec06-dangling-else.html",
  "statement": "Πολλές εμφωλευμένες εντολές `if` μπορεί να οδηγήσουν σε προβλήματα αμφισημίας (κάτι που δεν μας αρέσει καθόλου στο computer science). Είναι τα δύο προγράμματα ισοδύναμα;\n\n```c\nlab = -1;\nif (year < 1)\n    { /* empty block */ }\nelse if (year == 1)\n    lab = 20;\nelse\n    lab = 0;\n```\n\n```c\nlab = -1;\nif (year <= 1)\n    if (year == 1)\n        lab = 20;\nelse\n    lab = 0;\n```",
  "hint": "Ο μεταγλωττιστής αγνοεί τη στοίχιση. Βρείτε σε ποια `if` ανήκει το `else` του δεύτερου προγράμματος σύμφωνα με τον κανόνα της C, ξαναγράψτε το με αγκύλες και συγκρίνετε τα δύο προγράμματα για `year` ίσο με 0, 1 και 2."
 },
 {
  "id": "slides-lec06-do-while",
  "kind": "slides",
  "title": "Τι τυπώνει η do-while",
  "source": {
   "title": "Διάλεξη 6: Εντολές και Ροή Ελέγχου, διαφάνεια 26",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec06.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   6
  ],
  "topics": [
   "loops"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α6.1",
  "path": "questions/slides/slides-lec06-do-while.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec06-do-while.html",
  "statement": "Τι κάνει το παρακάτω πρόγραμμα;\n\n```c\ni = 0;\ndo\n   i++;\nwhile (i < 42);\nprintf(\"%d\\n\", i);\n```",
  "hint": "Η `do-while` εκτελεί πρώτα το σώμα και μετά ελέγχει τη συνθήκη. Ποια είναι η πρώτη τιμή του `i` για την οποία ο έλεγχος αποτυγχάνει;"
 },
 {
  "id": "slides-lec06-expression-statements",
  "kind": "slides",
  "title": "Τιμές μετά από εντολές έκφρασης",
  "source": {
   "title": "Διάλεξη 6: Εντολές και Ροή Ελέγχου, διαφάνεια 7",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec06.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   6,
   5
  ],
  "topics": [
   "statements",
   "operators"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α6.2",
  "path": "questions/slides/slides-lec06-expression-statements.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec06-expression-statements.html",
  "statement": "Ποια η τιμή των `x`, `y`, `z` μετά την εκτέλεση αυτών των εντολών έκφρασης;\n\n```c\nx = 4;\ny = 7;\nz = ++y;\ny = z - (x++);\nz = x - (--y);\n```",
  "hint": "Φτιάξτε έναν πίνακα με μία στήλη για κάθε μεταβλητή και μία γραμμή για κάθε εντολή. Θυμηθείτε ότι το `++y` αλλάζει πρώτα τη μεταβλητή και δίνει τη νέα τιμή, ενώ το `x++` δίνει την παλιά τιμή και αλλάζει τη μεταβλητή μετά."
 },
 {
  "id": "slides-lec06-for-count",
  "kind": "slides",
  "title": "Πόσες φορές εκτελείται μια for",
  "source": {
   "title": "Διάλεξη 6: Εντολές και Ροή Ελέγχου, διαφάνεια 24",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec06.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   6
  ],
  "topics": [
   "loops"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α6.3",
  "path": "questions/slides/slides-lec06-for-count.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec06-for-count.html",
  "statement": "Γενικό παράδειγμα:\n\n```c\nint i;\nfor ( i = 0 ; i < N ; i++ ) {\n    printf(\"%d\\n\", i);\n}\n```\n\nΠόσες φορές θα εκτελεστεί το block εντολών μέσα στην `for`; Θα τυπωθεί το `N`; Τι θα συμβεί αν αλλάξω την αρχικοποίηση ή το βήμα;",
  "hint": "Γράψτε τις τιμές του `i` για τις οποίες η συνθήκη είναι αληθής, για ένα μικρό `N` (π.χ. 3). Τι τιμή έχει το `i` τη στιγμή που ο βρόχος σταματάει; Δοκιμάστε μετά με `i = 1` ή με βήμα `i += 2`."
 },
 {
  "id": "slides-lec06-for-empty",
  "kind": "slides",
  "title": "Ο βρόχος for (;;)",
  "source": {
   "title": "Διάλεξη 6: Εντολές και Ροή Ελέγχου, διαφάνεια 23",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec06.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   6
  ],
  "topics": [
   "loops"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α6.4",
  "path": "questions/slides/slides-lec06-for-empty.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec06-for-empty.html",
  "statement": "Τι κάνει το παρακάτω πρόγραμμα;\n\n```c\nfor (;;)\n```",
  "hint": "Ποια από τα τρία μέρη της `for` είναι προαιρετικά; Πώς θεωρείται μια συνθήκη που λείπει;"
 },
 {
  "id": "slides-lec06-if-else-max",
  "kind": "slides",
  "title": "Μέγιστο με if-else και εναλλακτικές",
  "source": {
   "title": "Διάλεξη 6: Εντολές και Ροή Ελέγχου, διαφάνεια 13",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec06.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   6,
   5
  ],
  "topics": [
   "conditionals"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α6.5",
  "path": "questions/slides/slides-lec06-if-else-max.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec06-if-else-max.html",
  "statement": "Δίνεται ο κώδικας:\n\n```c\nif (x > y)\n    max = x;\nelse\n    max = y;\n```\n\n- Θα μπορούσαμε να \"ζήσουμε\" χωρίς `else`;\n- Υπάρχει εναλλακτικός τρόπος να γράψουμε το παραπάνω;\n- Τι κάνουμε όταν έχουμε πάνω από δύο συνθήκες;",
  "hint": "Για το πρώτο ερώτημα, σκεφτείτε τι θα γινόταν αν δίνατε μια αρχική τιμή στο `max` πριν από την `if`. Για το δεύτερο, θυμηθείτε τους τελεστές της προηγούμενης διάλεξης: υπάρχει ένας που επιλέγει ανάμεσα σε δύο τιμές μέσα σε μία έκφραση. Για το τρίτο, σκεφτείτε τι επιτρέπεται να είναι η εντολή μετά το `else`."
 },
 {
  "id": "slides-lec06-while-forever",
  "kind": "slides",
  "title": "Ο βρόχος while (1)",
  "source": {
   "title": "Διάλεξη 6: Εντολές και Ροή Ελέγχου, διαφάνεια 20",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec06.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   6
  ],
  "topics": [
   "loops"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α6.6",
  "path": "questions/slides/slides-lec06-while-forever.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec06-while-forever.html",
  "statement": "Τι κάνει το παρακάτω πρόγραμμα;\n\n```c\nwhile (1);\n```\n\nΥπάρχει κάποια χρησιμότητα στο να έχουμε μια λογική συνθήκη που είναι πάντα αληθής;",
  "hint": "Ποια είναι η τιμή αλήθειας του `1` στην C και ποιο είναι το σώμα αυτού του βρόχου; Για το δεύτερο ερώτημα, σκεφτείτε προγράμματα που δεν πρέπει να σταματούν ποτέ μόνα τους."
 },
 {
  "id": "slides-lec06-while-semicolon",
  "kind": "slides",
  "title": "Το ερωτηματικό μετά το while",
  "source": {
   "title": "Διάλεξη 6: Εντολές και Ροή Ελέγχου, διαφάνεια 21",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec06.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   6
  ],
  "topics": [
   "loops",
   "statements"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α6.9",
  "path": "questions/slides/slides-lec06-while-semicolon.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec06-while-semicolon.html",
  "statement": "Τι κάνει το παρακάτω πρόγραμμα;\n\n```c\ni = 0;\nwhile (i < 42);\n  printf(\"%d\\n\", i++);\n```",
  "hint": "Μην εμπιστεύεστε τη στοίχιση. Ποια ακριβώς εντολή είναι το σώμα του βρόχου; Αλλάζει ποτέ το `i` μέσα σε αυτό;"
 },
 {
  "id": "slides-lec06-while-sum",
  "kind": "slides",
  "title": "Άθροισμα με while",
  "source": {
   "title": "Διάλεξη 6: Εντολές και Ροή Ελέγχου, διαφάνεια 19",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec06.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   6
  ],
  "topics": [
   "loops"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α6.7",
  "path": "questions/slides/slides-lec06-while-sum.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec06-while-sum.html",
  "statement": "Τι κάνει το παρακάτω πρόγραμμα;\n\n```c\nint i = 0;\nint sum = 0;\nwhile (i < 42) {\n  sum += i;\n  i++;\n}\nprintf(\"%d %d\\n\", i, sum);\n```",
  "hint": "Ποια είναι η πρώτη τιμή του `i` για την οποία η συνθήκη είναι ψευδής; Ποιες τιμές έχουν προστεθεί στο `sum` μέχρι τότε; Ο τύπος για το άθροισμα $1 + 2 + \\dots + n$ θα σας γλιτώσει από τις πράξεις."
 },
 {
  "id": "slides-lec07-even-descending",
  "kind": "slides",
  "title": "Τριψήφιοι άρτιοι σε φθίνουσα σειρά",
  "source": {
   "title": "Διάλεξη 7: Επίλυση Προβλημάτων, διαφάνεια 14",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec07.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   7
  ],
  "topics": [
   "loops",
   "problem-solving"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α7.1",
  "path": "questions/slides/slides-lec07-even-descending.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec07-even-descending.html",
  "statement": "Θέλω να τυπώσω όλους τους τριψήφιους άρτιους σε φθίνουσα σειρά (998 996 994 … 100). Πως;",
  "hint": "Ποιος είναι ο πρώτος αριθμός που πρέπει να τυπωθεί, ποιος ο τελευταίος, και πόσο απέχουν δύο διαδοχικοί; Αυτά τα τρία δίνουν την αρχικοποίηση, τη συνθήκη και το βήμα μιας `for`, όπου η μεταβλητή μειώνεται."
 },
 {
  "id": "slides-lec07-odd-multiples-of-7",
  "kind": "slides",
  "title": "Γινόμενο τριψήφιων περιττών πολλαπλασίων του 7",
  "source": {
   "title": "Διάλεξη 7: Επίλυση Προβλημάτων, διαφάνεια 16",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec07.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   7
  ],
  "topics": [
   "loops",
   "problem-solving",
   "operators"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α7.2",
  "path": "questions/slides/slides-lec07-odd-multiples-of-7.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec07-odd-multiples-of-7.html",
  "statement": "Θέλω να βρω το γινόμενο όλων των τριψήφιων περιττών που διαιρούνται με το 7. Πως;",
  "hint": "Μπορείτε να διατρέξετε τους τριψήφιους περιττούς και να κρατήσετε όσους έχουν `i % 7 == 0`, ή να βρείτε το πρώτο τέτοιο πολλαπλάσιο και το σταθερό βήμα ανάμεσα σε διαδοχικά. Προσέξτε από πού ξεκινά ο συσσωρευτής του γινομένου, και εκτιμήστε πόσο μεγάλο θα βγει το αποτέλεσμα πριν διαλέξετε τύπο."
 },
 {
  "id": "slides-lec08-digit-names",
  "kind": "slides",
  "title": "Το αγγλικό όνομα κάθε ψηφίου",
  "source": {
   "title": "Διάλεξη 8: Ροή Ελέγχου #2, διαφάνεια 13",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec08.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   8
  ],
  "topics": [
   "conditionals",
   "control-flow"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α8.1",
  "path": "questions/slides/slides-lec08-digit-names.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec08-digit-names.html",
  "statement": "Θέλω να τυπώσω το αγγλικό όνομα κάθε ψηφίου (`zero`, `one`, …, `nine`), και\n`unknown` για οποιαδήποτε άλλη τιμή. Πώς;",
  "hint": "Μια αλυσίδα `else if` δουλεύει, αλλά όλες οι συνθήκες συγκρίνουν την ίδια ακέραια\nμεταβλητή με σταθερές: αυτή είναι η περίπτωση της `switch`. Μην ξεχάσετε τι\nχρειάζεται στο τέλος κάθε `case` και πού πάνε οι τιμές που δεν είναι ψηφία."
 },
 {
  "id": "slides-lec08-print-all-issue",
  "kind": "slides",
  "title": "Υπάρχει θέμα με αυτή την υλοποίηση;",
  "source": {
   "title": "Διάλεξη 8: Ροή Ελέγχου #2, διαφάνεια 7",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec08.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   8
  ],
  "topics": [
   "loops",
   "control-flow"
  ],
  "difficulty": 1,
  "type": "debug",
  "label": "Α8.2",
  "path": "questions/slides/slides-lec08-print-all-issue.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec08-print-all-issue.html",
  "statement": "Θέλω να τυπώσω (αν υπάρχει) τον μικρότερο τριψήφιο που είναι πολλαπλάσιο του 2 και\nτου 5 αλλά όχι του 4. Πώς;\n\n```c\nfor(i = 100 ; i < 1000 ; i++) {\n  if (i % 2 == 0 && i % 5 == 0 && i % 4 != 0) {\n      printf(\"%d\\n\", i);\n  }\n}\n```\n\nΥπάρχει κάποιο θέμα με αυτήν την υλοποίηση;",
  "hint": "Τι γίνεται αφού ο βρόχος βρει και τυπώσει τον πρώτο κατάλληλο αριθμό; Μετρήστε πόσες\nγραμμές θα τυπωθούν και σκεφτείτε πώς σταματάμε έναν βρόχο νωρίς."
 },
 {
  "id": "slides-lec08-product-multiples-of-7",
  "kind": "slides",
  "title": "Γινόμενο τριψήφιων περιττών πολλαπλασίων του 7",
  "source": {
   "title": "Διάλεξη 8: Ροή Ελέγχου #2, διαφάνεια 5",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec08.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   8
  ],
  "topics": [
   "loops"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α8.3",
  "path": "questions/slides/slides-lec08-product-multiples-of-7.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec08-product-multiples-of-7.html",
  "statement": "Θέλω να βρω το γινόμενο όλων των τριψήφιων περιττών που διαιρούνται με το 7. Πώς;",
  "hint": "Υπάρχουν δύο δρόμοι: διατρέξτε τους τριψήφιους περιττούς και κρατήστε με μια `if`\nόσους διαιρούνται με το 7, ή βρείτε τον πρώτο τέτοιο αριθμό και το σταθερό βήμα\nανάμεσα σε διαδοχικούς, ώστε ο βρόχος να μη χρειάζεται `if`. Ελέγξτε με το χέρι τις\nπρώτες τιμές του μετρητή και σκεφτείτε αν το αποτέλεσμα χωράει σε `int`."
 },
 {
  "id": "slides-lec08-product-overflow",
  "kind": "slides",
  "title": "Αρνητικό γινόμενο σε βρόχο",
  "source": {
   "title": "Διάλεξη 8: Ροή Ελέγχου #2, διαφάνεια 2",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec08.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   8,
   2
  ],
  "topics": [
   "integer-representation",
   "loops"
  ],
  "difficulty": 1,
  "type": "debug",
  "label": "Α8.4",
  "path": "questions/slides/slides-lec08-product-overflow.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec08-product-overflow.html",
  "statement": "Έτρεξα τον παρακάτω πολλαπλασιασμό:\n\n```c\nfor(prod = 1, i = 105 ; i <= 999 ; i += 14) {\n    prod *= i;\n}\n```\n\nκαι μου τύπωσε το παρακάτω. Τι συμβαίνει;\n\n```text\n$ ./prod\n-1187656959\n```",
  "hint": "Πόσους παράγοντες πολλαπλασιάζει ο βρόχος και πόσο μεγάλο είναι περίπου το σωστό\nγινόμενο; Συγκρίνετέ το με τη μέγιστη τιμή που χωράει σε έναν `int` των 32 bit."
 },
 {
  "id": "slides-lec08-season",
  "kind": "slides",
  "title": "Η εποχή κάθε μήνα",
  "source": {
   "title": "Διάλεξη 8: Ροή Ελέγχου #2, διαφάνεια 17",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec08.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   8
  ],
  "topics": [
   "conditionals",
   "control-flow"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α8.5",
  "path": "questions/slides/slides-lec08-season.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec08-season.html",
  "statement": "Θέλω να τυπώσω την εποχή κάθε μήνα (`winter`, `spring`, `summer`, …), με τον\nμήνα ως ακέραιο από 1 έως 12. Πώς;",
  "hint": "Με `switch` στον μήνα: κάθε εποχή αντιστοιχεί σε τρεις μήνες, οπότε γράψτε τα\nτρία `case` το ένα κάτω από το άλλο και τις κοινές εντολές μετά το τελευταίο.\nΠροσέξτε ότι ο χειμώνας περιλαμβάνει τον Δεκέμβριο."
 },
 {
  "id": "slides-lec08-smallest-three-digit",
  "kind": "slides",
  "title": "Ο μικρότερος τριψήφιος πολλαπλάσιο του 2 και του 5 αλλά όχι του 4",
  "source": {
   "title": "Διάλεξη 8: Ροή Ελέγχου #2, διαφάνεια 6",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec08.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   8
  ],
  "topics": [
   "loops",
   "control-flow"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α8.6",
  "path": "questions/slides/slides-lec08-smallest-three-digit.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec08-smallest-three-digit.html",
  "statement": "Θέλω να τυπώσω (αν υπάρχει) τον μικρότερο τριψήφιο που είναι πολλαπλάσιο του 2 και\nτου 5 αλλά όχι του 4. Πώς;",
  "hint": "Διατρέξτε τους τριψήφιους σε αύξουσα σειρά και ελέγξτε τη συνθήκη με τον τελεστή\n`%`. Ο βρόχος πρέπει να σταματήσει μόλις βρει τον πρώτο αριθμό: με μια\nμεταβλητή-σημαία στη συνθήκη του ή με `break`."
 },
 {
  "id": "slides-lec09-addnums",
  "kind": "slides",
  "title": "Άθροισμα δύο αριθμών από την πρότυπη είσοδο",
  "source": {
   "title": "Διάλεξη 9: Δεδομένα Εισόδου, διαφάνεια 25–26",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec09.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output",
   "input-validation",
   "functions"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α9.4",
  "path": "questions/slides/slides-lec09-addnums.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec09-addnums.html",
  "statement": "Θέλω να διαβάσω δύο αριθμούς από την πρότυπη είσοδο και να τους προσθέσω. Πώς;\n\n```text\n$ ./addnums\nGive me a number: 40\nGive me another number: 2\nTotal: 42\n```\n\nΗ διάλεξη δείχνει έναν τρόπο με τη `getchar`, φτιάχνοντας μια συνάρτηση `getinteger` που διαβάζει τους χαρακτήρες έναν-έναν και τους μετατρέπει σε αριθμό. Υπάρχει άλλος τρόπος να επιτύχουμε το ίδιο αποτέλεσμα;",
  "hint": "Με τη `getchar`, κάθε νέο ψηφίο `ch` αλλάζει την τιμή σε `10 * val + (ch - '0')`, μέχρι να διαβαστεί το `'\\n'`. Ο άλλος τρόπος είναι μια συνάρτηση της `stdio.h` που είναι η «συμμετρική» της `printf`· μην ξεχάσετε να ελέγξετε τι επιστρέφει."
 },
 {
  "id": "slides-lec09-cat-char",
  "kind": "slides",
  "title": "Μια cat με char",
  "source": {
   "title": "Διάλεξη 9: Δεδομένα Εισόδου, διαφάνεια 23",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec09.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output",
   "types"
  ],
  "difficulty": 2,
  "type": "debug",
  "label": "Α9.5",
  "path": "questions/slides/slides-lec09-cat-char.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec09-cat-char.html",
  "statement": "Τι πρόβλημα έχει η παρακάτω υλοποίηση της `cat`;\n\n```c\n#include <stdio.h>\n\nint main() {\n  char c;\n  while((c = getchar()) != EOF)\n    putchar(c);\n  return 0;\n}\n```",
  "hint": "Πόσες διαφορετικές τιμές μπορεί να επιστρέψει η `getchar` και πόσες χωράει ένα `char`; Δοκιμάστε την είσοδο `echo -e \"hello\\xffworld\" | ./cat` και σκεφτείτε ποια τιμή παίρνει το `c` για το byte `0xff`."
 },
 {
  "id": "slides-lec09-charcount",
  "kind": "slides",
  "title": "Μετρητής χαρακτήρων με getchar",
  "source": {
   "title": "Διάλεξη 9: Δεδομένα Εισόδου, διαφάνεια 20",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec09.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output",
   "loops"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α9.1",
  "path": "questions/slides/slides-lec09-charcount.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec09-charcount.html",
  "statement": "Διαδοχικές κλήσεις της `getchar()` διαβάζουν διαδοχικούς χαρακτήρες. Τι κάνει το παρακάτω πρόγραμμα;\n\n```c\n#include <stdio.h>\nint main() {\n  int ch, sum = 0;\n  printf(\"Enter characters: \");\n  while( (ch = getchar()) != EOF ) {\n    printf(\"%c\", ch);\n    sum++;\n  }\n  printf(\"\\nTotal characters: %d\\n\", sum);\n  return 0;\n}\n```",
  "hint": "Ακολουθήστε τον βρόχο για μια μικρή είσοδο, π.χ. `hi` και Enter, και μετά Ctrl+D. Μην ξεχάσετε ότι και το Enter φτάνει στο πρόγραμμα ως χαρακτήρας."
 },
 {
  "id": "slides-lec09-float-equality",
  "kind": "slides",
  "title": "OK ή Not OK;",
  "source": {
   "title": "Διάλεξη 9: Δεδομένα Εισόδου, διαφάνεια 3",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec09.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "floating-point",
   "operators"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α9.6",
  "path": "questions/slides/slides-lec09-float-equality.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec09-float-equality.html",
  "statement": "Τι θα τυπώσει το παρακάτω πρόγραμμα; Υπάρχει κάποια εξήγηση;\n\n```c\n#include <stdio.h>\nint main() {\n    float a = 3.1;\n\n    if(a == 3.1)\n       printf(\"OK\\n\");\n    else\n       printf(\"Not OK\\n\");\n    return 0;\n}\n```",
  "hint": "Ποιος είναι ο τύπος της σταθεράς `3.1` και ποιος του `a`; Αναπαρίσταται το `3.1` ακριβώς σε δυαδική μορφή, και πόσα ψηφία ακρίβειας κρατά ένα `float` σε σχέση με ένα `double`;"
 },
 {
  "id": "slides-lec09-getinteger",
  "kind": "slides",
  "title": "Η συνάρτηση getinteger",
  "source": {
   "title": "Διάλεξη 9: Δεδομένα Εισόδου, διαφάνεια 26, 38",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec09.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output",
   "functions",
   "input-validation"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α9.7",
  "path": "questions/slides/slides-lec09-getinteger.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec09-getinteger.html",
  "statement": "Τι κάνει το παρακάτω πρόγραμμα;\n\n```c\n#define ERROR -1          // Return value for illegal character\n\nint getinteger(int base) {\n  int ch;                 // No need to declare ch as int - no EOF handling\n  int val = 0;                               // Initialize return value\n  while ((ch = getchar()) != '\\n')           // Read up to new line\n    if (ch >= '0' && ch <= '0' + base - 1)   // Legal character?\n      val = base * val + (ch - '0');         // Update return value\n    else\n      return ERROR;                          // Illegal character read\n  return val;   // Everything OK - Return value of number read\n}\n```",
  "hint": "Ιχνηλατήστε το `val` για την κλήση `getinteger(10)` με είσοδο `42` και για την `getinteger(2)` με είσοδο `101`. Τι τιμή έχει το `ch - '0'` για έναν χαρακτήρα-ψηφίο; Τι γίνεται αν εμφανιστεί γράμμα;"
 },
 {
  "id": "slides-lec09-letter-frequencies",
  "kind": "slides",
  "title": "Μέτρηση γραμμάτων στην είσοδο",
  "source": {
   "title": "Διάλεξη 9: Δεδομένα Εισόδου, διαφάνεια 39",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec09.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output",
   "arrays"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α9.8",
  "path": "questions/slides/slides-lec09-letter-frequencies.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec09-letter-frequencies.html",
  "statement": "Τι κάνει το παρακάτω πρόγραμμα;\n\n```c\nint i, ch, total = 0;\nint letfr[26];  // Letter occurrences and frequencies array\nfor (i=0 ; i < 26 ; i++)\n  letfr[i] = 0;\nwhile ((ch = getchar()) != EOF) {\n  if (ch >= 'A' && ch <= 'Z') {\n    letfr[ch-'A']++;            // Found upper case letter\n    total++;\n  }\n  if (ch >= 'a' && ch <= 'z') {\n    letfr[ch-'a']++;            // Found lower case letter\n    total++;\n  }\n}\n```",
  "hint": "Ποια θέση του πίνακα `letfr` αυξάνεται όταν διαβαστεί το `'C'` και ποια όταν διαβαστεί το `'c'`; Τι μετρά το `total` και τι γίνεται με τα ψηφία και τα κενά;"
 },
 {
  "id": "slides-lec09-scanf-no-ampersand",
  "kind": "slides",
  "title": "scanf χωρίς &",
  "source": {
   "title": "Διάλεξη 9: Δεδομένα Εισόδου, διαφάνεια 32",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec09.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output",
   "pointers"
  ],
  "difficulty": 2,
  "type": "short-answer",
  "label": "Α9.9",
  "path": "questions/slides/slides-lec09-scanf-no-ampersand.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec09-scanf-no-ampersand.html",
  "statement": "Στο πρόγραμμα\n\n```c\n#include <stdio.h>\nint main() {\n  int n;\n  printf(\"Gimme a number: \");\n  scanf(\"%d\", &n);\n  printf(\"Square: %d\\n\", n * n);\n  return 0;\n}\n```\n\nτι θα γινόταν αν γράφαμε `scanf(\"%d\", n);`; Γιατί;\n\n```text\n$ ./scanf\nGimme a number: 3\nSegmentation fault\n```",
  "hint": "Η C περνάει τα ορίσματα με τιμή. Τι παίρνει η `scanf` στη μία και τι στην άλλη περίπτωση, και πού προσπαθεί να γράψει τον αριθμό που διάβασε;"
 },
 {
  "id": "slides-lec09-scanf-return",
  "kind": "slides",
  "title": "Είναι σωστό αυτό το πρόγραμμα;",
  "source": {
   "title": "Διάλεξη 9: Δεδομένα Εισόδου, διαφάνεια 33–35",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec09.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output",
   "input-validation"
  ],
  "difficulty": 2,
  "type": "debug",
  "label": "Α9.10",
  "path": "questions/slides/slides-lec09-scanf-return.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec09-scanf-return.html",
  "statement": "Είναι σωστό αυτό το πρόγραμμα;\n\n```c\n#include <stdio.h>\nint main() {\n  int n;\n  printf(\"Gimme a number: \");\n  scanf(\"%d\", &n);\n  printf(\"Square: %d\\n\", n * n);\n  return 0;\n}\n```\n\n```text\n$ ./scanf\nGimme a number: 16\nSquare: 256\n$ ./scanf\nGimme a number: Square:\n1068701481\n$ ./scanf\nGimme a number: hello\nSquare: 1072038564\n```",
  "hint": "Τι επιστρέφει η `scanf` όταν πατήσετε Ctrl+D και τι όταν γράψετε `hello`; Ποια τιμή έχει το `n` σε αυτές τις περιπτώσεις, αφού δεν αρχικοποιήθηκε ποτέ;"
 },
 {
  "id": "slides-lec09-scanf-square",
  "kind": "slides",
  "title": "Τι κάνει το πρόγραμμα με τη scanf;",
  "source": {
   "title": "Διάλεξη 9: Δεδομένα Εισόδου, διαφάνεια 30",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec09.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α9.2",
  "path": "questions/slides/slides-lec09-scanf-square.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec09-scanf-square.html",
  "statement": "Τι κάνει το παρακάτω πρόγραμμα;\n\n```c\n#include <stdio.h>\nint main() {\n  int n;\n  printf(\"Gimme a number: \");\n  scanf(\"%d\", &n);\n  printf(\"Square: %d\\n\", n * n);\n  return 0;\n}\n```",
  "hint": "Τι σημαίνει η προδιαγραφή `%d` στη `scanf`, και γιατί μπροστά από το `n` υπάρχει `&`; Τι γράφεται στο `stdout` αν δώσετε `16`;"
 },
 {
  "id": "slides-lec09-scanf-two",
  "kind": "slides",
  "title": "scanf με πολλά ορίσματα",
  "source": {
   "title": "Διάλεξη 9: Δεδομένα Εισόδου, διαφάνεια 36–37",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec09.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   9
  ],
  "topics": [
   "input-output"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α9.3",
  "path": "questions/slides/slides-lec09-scanf-two.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec09-scanf-two.html",
  "statement": "Τι κάνει το παρακάτω πρόγραμμα; Τι τυπώνει με είσοδο `   2   4` (με επιπλέον κενά);\n\n```c\n#include <stdio.h>\nint main() {\n  int n1, n2;\n  printf(\"Gimme two numbers: \");\n  scanf(\"%d %d\", &n1, &n2);\n  printf(\"Result: %d\\n\", n1 * n2);\n  return 0;\n}\n```",
  "hint": "Τι κάνει η `%d` με τους κενούς χαρακτήρες και τις αλλαγές γραμμής που συναντά πριν από το πρώτο ψηφίο;"
 },
 {
  "id": "slides-lec10-addnums",
  "kind": "slides",
  "title": "Πρόσθεση δύο αριθμών από την είσοδο",
  "source": {
   "title": "Διάλεξη 10, διαφάνεια 5",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec10.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   10,
   9
  ],
  "topics": [
   "input-output"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α10.1",
  "path": "questions/slides/slides-lec10-addnums.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec10-addnums.html",
  "statement": "Θέλω να διαβάσω δύο αριθμούς από την πρότυπη είσοδο και να τους προσθέσω. Πώς;\n\n```text\n$ ./addnums\nGive me a number: 40\nGive me another number: 2\nTotal: 42\n```\n\nΈνας τρόπος είναι να χρησιμοποιήσουμε την `getchar` και να φτιάξουμε μια συνάρτηση\n`getinteger` που διαβάζει τους χαρακτήρες έναν-έναν και τους μετατρέπει σε αριθμό.\nΥπάρχει άλλος τρόπος να επιτύχουμε το ίδιο αποτέλεσμα; Γράψτε το πρόγραμμα\n`addnums.c`.",
  "hint": "Η πρότυπη βιβλιοθήκη έχει μια «αδελφή» της `printf` για διάβασμα. Θυμηθείτε ότι\nπρέπει να της δώσετε πού να αποθηκεύσει κάθε τιμή, και ελέγξτε τι επιστρέφει."
 },
 {
  "id": "slides-lec10-array-assign",
  "kind": "slides",
  "title": "Ανάθεση πίνακα σε πίνακα",
  "source": {
   "title": "Διάλεξη 10, διαφάνεια 42",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec10.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   10
  ],
  "topics": [
   "arrays"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α10.2",
  "path": "questions/slides/slides-lec10-array-assign.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec10-array-assign.html",
  "statement": "Μπορώ να αναθέσω τα στοιχεία ενός πίνακα σε άλλον;\n\n```c\nint a[3] = {1, 2, 3};\nint b[3] = {4, 5, 6};\nb = a;\n```",
  "hint": "Δοκιμάστε να το μεταγλωττίσετε με `gcc`. Αν δεν επιτρέπεται, πώς θα αντιγράφατε τα\nστοιχεία;"
 },
 {
  "id": "slides-lec10-array-memory",
  "kind": "slides",
  "title": "Ποιος πίνακας πιάνει περισσότερη μνήμη;",
  "source": {
   "title": "Διάλεξη 10, διαφάνεια 40",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec10.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   10
  ],
  "topics": [
   "arrays",
   "types",
   "memory-model"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α10.3",
  "path": "questions/slides/slides-lec10-array-memory.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec10-array-memory.html",
  "statement": "Πίνακες μπορούν να οριστούν για όλους τους τύπους της C. Παράδειγμα:\n\n```c\nint a[1024];\nchar b[2048];\ndouble c[512];\n```\n\nΠοιος από τους παραπάνω πίνακες καταλαμβάνει περισσότερη μνήμη;",
  "hint": "Ένας πίνακας πιάνει «πλήθος στοιχείων × μέγεθος τύπου» bytes. Θυμηθείτε τα\nσυνηθισμένα `sizeof` των `int`, `char` και `double`."
 },
 {
  "id": "slides-lec10-atoi",
  "kind": "slides",
  "title": "Η συνάρτηση atoi",
  "source": {
   "title": "Διάλεξη 10, διαφάνειες 49-50",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec10.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   10
  ],
  "topics": [
   "arrays",
   "strings",
   "functions"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α10.10",
  "path": "questions/slides/slides-lec10-atoi.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec10-atoi.html",
  "statement": "Θέλω μια συνάρτηση `atoi` που να παίρνει ένα πίνακα χαρακτήρων (μόνο ψηφία) και να\nεπιστρέφει έναν ακέραιο. Πώς;\n\nΑφού τη γράψετε: τι μπορεί να πάει στραβά με αυτήν τη συνάρτηση;",
  "hint": "Πώς ξέρετε πού τελειώνει ο πίνακας χαρακτήρων; Η μετατροπή είναι ίδια με της\n`getinteger` σε βάση 10. Για το δεύτερο σκέλος, σκεφτείτε εισόδους που δεν είναι\n«μόνο ψηφία» ή είναι πολύ μεγάλες."
 },
 {
  "id": "slides-lec10-average",
  "kind": "slides",
  "title": "Μέσος όρος πίνακα",
  "source": {
   "title": "Διάλεξη 10, διαφάνειες 45-46",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec10.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   10
  ],
  "topics": [
   "arrays",
   "functions"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α10.4",
  "path": "questions/slides/slides-lec10-average.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec10-average.html",
  "statement": "Θέλω μια συνάρτηση που να δέχεται έναν πίνακα 100 ακεραίων και να επιστρέφει τον\nμέσο όρο. Πώς;",
  "hint": "Χρησιμοποιήστε έναν συσσωρευτή που ξεκινά από 0. Προσέξτε τι τύπο επιστρέφετε και\nαν η διαίρεση είναι ακέραια."
 },
 {
  "id": "slides-lec10-find-max",
  "kind": "slides",
  "title": "Το μεγαλύτερο αρκουδάκι",
  "source": {
   "title": "Διάλεξη 10, διαφάνειες 21-26 και 37",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec10.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   10
  ],
  "topics": [
   "arrays",
   "functions"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α10.6",
  "path": "questions/slides/slides-lec10-find-max.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec10-find-max.html",
  "statement": "Έστω ότι έχω 100 αρκουδάκια και ψάχνω να βρω το μεγαλύτερο. Τι μπορώ να κάνω για\nνα το βρω; Στόχος: ελαχιστοποίηση του κόπου.\n\nΑναπαριστούμε κάθε αρκουδάκι με έναν ακέραιο (`int`). Γράψτε μια συνάρτηση\n`find_max` που να παίρνει έναν πίνακα 100 στοιχείων και να γυρίζει το μέγιστο.",
  "hint": "Κρατήστε το «μεγαλύτερο μέχρι τώρα» και κοιτάξτε κάθε στοιχείο μία φορά. Με τι τιμή\nπρέπει να ξεκινά αυτό, ώστε η συνάρτηση να δουλεύει και αν όλα τα στοιχεία είναι\nαρνητικά;"
 },
 {
  "id": "slides-lec10-find",
  "kind": "slides",
  "title": "Αναζήτηση στοιχείου σε πίνακα",
  "source": {
   "title": "Διάλεξη 10, διαφάνειες 47-48",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec10.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   10
  ],
  "topics": [
   "arrays",
   "functions",
   "searching"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α10.5",
  "path": "questions/slides/slides-lec10-find.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec10-find.html",
  "statement": "Θέλω μια συνάρτηση που να δέχεται έναν πίνακα 100 ακεραίων και έναν ακέραιο και να\nγυρνάει τη θέση του στοιχείου αν το βρήκε ή -1. Πώς;",
  "hint": "Ελέγξτε τα στοιχεία ένα-ένα και επιστρέψτε μόλις βρείτε αυτό που ψάχνετε. Πότε\nείστε σίγουροι ότι το στοιχείο δεν υπάρχει;"
 },
 {
  "id": "slides-lec10-getinteger",
  "kind": "slides",
  "title": "Τι κάνει η getinteger;",
  "source": {
   "title": "Διάλεξη 10, διαφάνεια 17",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec10.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   10,
   9
  ],
  "topics": [
   "input-output",
   "functions"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α10.11",
  "path": "questions/slides/slides-lec10-getinteger.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec10-getinteger.html",
  "statement": "Τι κάνει το παρακάτω πρόγραμμα;\n\n```c\n#define ERROR -1\n\nint getinteger(int base) {\n  int ch;\n  int val = 0;\n  while ((ch = getchar()) != '\\n')\n    if (ch >= '0' && ch <= '0' + base - 1)\n      val = base * val + (ch - '0');\n    else\n      return ERROR;\n  return val;\n}\n```",
  "hint": "Εκτελέστε τη με το χέρι για `base = 10` και είσοδο `472`, και μετά για `base = 2`\nκαι είσοδο `101`. Ποιοι χαρακτήρες θεωρούνται νόμιμοι για κάθε βάση;"
 },
 {
  "id": "slides-lec10-letter-frequency",
  "kind": "slides",
  "title": "Τι κάνει ο πίνακας letfr;",
  "source": {
   "title": "Διάλεξη 10, διαφάνεια 18",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec10.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   10
  ],
  "topics": [
   "arrays",
   "input-output"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α10.12",
  "path": "questions/slides/slides-lec10-letter-frequency.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec10-letter-frequency.html",
  "statement": "Τι κάνει το παρακάτω πρόγραμμα;\n\n```c\nint i, ch, total = 0;\nint letfr[26];  // Letter occurrences and frequencies array\nfor (i=0 ; i < 26 ; i++)\n  letfr[i] = 0;\nwhile ((ch = getchar()) != EOF) {\n  if (ch >= 'A' && ch <= 'Z') {\n    letfr[ch-'A']++;            // Found upper case letter\n    total++;\n  }\n  if (ch >= 'a' && ch <= 'z') {\n    letfr[ch-'a']++;            // Found lower case letter\n    total++;\n  }\n}\n```",
  "hint": "Υπολογίστε τι τιμή έχει η έκφραση `ch - 'A'` για `ch = 'A'`, `'B'` και `'Z'`. Τι\nμετράει λοιπόν το `letfr[i]` και τι το `total`;"
 },
 {
  "id": "slides-lec10-out-of-bounds",
  "kind": "slides",
  "title": "Πρόσβαση εκτός ορίων πίνακα",
  "source": {
   "title": "Διάλεξη 10, διαφάνεια 44",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec10.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   10
  ],
  "topics": [
   "arrays",
   "undefined-behavior"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α10.7",
  "path": "questions/slides/slides-lec10-out-of-bounds.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec10-out-of-bounds.html",
  "statement": "Για τον πίνακα `int bears[100];`, τι θα συμβεί αν προσπελάσω εκτός ορίων, π.χ.\n`bears[100]` ή `bears[-1]`;",
  "hint": "Ποιες είναι οι έγκυρες θέσεις; Σκεφτείτε αν η C ελέγχει τα όρια και πώς\nκατατάσσει το standard αυτή τη χρήση."
 },
 {
  "id": "slides-lec10-scanf-correct",
  "kind": "slides",
  "title": "Είναι σωστό αυτό το πρόγραμμα;",
  "source": {
   "title": "Διάλεξη 10, διαφάνειες 12-14",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec10.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   10
  ],
  "topics": [
   "input-output",
   "input-validation"
  ],
  "difficulty": 2,
  "type": "debug",
  "label": "Α10.13",
  "path": "questions/slides/slides-lec10-scanf-correct.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec10-scanf-correct.html",
  "statement": "Είναι σωστό αυτό το πρόγραμμα;\n\n```c\n#include <stdio.h>\n\nint main() {\n  int n;\n  printf(\"Gimme a number: \");\n  scanf(\"%d\", &n);\n  printf(\"Square: %d\\n\", n * n);\n  return 0;\n}\n```\n\nΜερικές εκτελέσεις:\n\n```text\n$ ./scanf\nGimme a number: 16\nSquare: 256\n$ ./scanf\nGimme a number: Square:\n1068701481\n$ ./scanf\nGimme a number: hello\nSquare: 1072038564\n```",
  "hint": "Η `scanf` επιστρέφει κάτι. Τι επιστρέφει όταν τελειώσει η είσοδος και τι όταν η\nείσοδος δεν είναι αριθμός; Τι τιμή έχει η `n` σε αυτές τις περιπτώσεις;"
 },
 {
  "id": "slides-lec10-scanf-no-ampersand",
  "kind": "slides",
  "title": "scanf χωρίς &",
  "source": {
   "title": "Διάλεξη 10, διαφάνεια 11",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec10.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   10,
   11
  ],
  "topics": [
   "input-output",
   "pointers"
  ],
  "difficulty": 2,
  "type": "debug",
  "label": "Α10.14",
  "path": "questions/slides/slides-lec10-scanf-no-ampersand.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec10-scanf-no-ampersand.html",
  "statement": "Στο πρόγραμμα:\n\n```c\n#include <stdio.h>\n\nint main() {\n  int n;\n  printf(\"Gimme a number: \");\n  scanf(\"%d\", &n);\n  printf(\"Square: %d\\n\", n * n);\n  return 0;\n}\n```\n\nΤι θα γινόταν αν γράφαμε `scanf(\"%d\", n);`; Γιατί;\n\n```text\n$ ./scanf\nGimme a number: 3\nSegmentation fault\n```",
  "hint": "Σκεφτείτε τι παίρνει μια συνάρτηση όταν της περνάμε μια μεταβλητή με τιμή, και τι\nτιμή έχει η `n` τη στιγμή της κλήσης. Πού θα προσπαθήσει να γράψει η `scanf`;"
 },
 {
  "id": "slides-lec10-scanf-square",
  "kind": "slides",
  "title": "Τι κάνει το πρόγραμμα με τη scanf;",
  "source": {
   "title": "Διάλεξη 10, διαφάνειες 9-10",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec10.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   10
  ],
  "topics": [
   "input-output"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α10.8",
  "path": "questions/slides/slides-lec10-scanf-square.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec10-scanf-square.html",
  "statement": "Τι κάνει το παρακάτω πρόγραμμα;\n\n```c\n#include <stdio.h>\n\nint main() {\n  int n;\n  printf(\"Gimme a number: \");\n  scanf(\"%d\", &n);\n  printf(\"Square: %d\\n\", n * n);\n  return 0;\n}\n```",
  "hint": "Διαβάστε τη `scanf` ως την «αντίστροφη» της `printf`. Τι ρόλο παίζει το `&` μπροστά\nαπό το `n`;"
 },
 {
  "id": "slides-lec10-scanf-two-numbers",
  "kind": "slides",
  "title": "scanf με πολλά ορίσματα",
  "source": {
   "title": "Διάλεξη 10, διαφάνειες 15-16",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec10.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   10
  ],
  "topics": [
   "input-output"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α10.9",
  "path": "questions/slides/slides-lec10-scanf-two-numbers.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec10-scanf-two-numbers.html",
  "statement": "Τι κάνει το παρακάτω πρόγραμμα; Τι θα τυπώσει αν δώσουμε ως είσοδο `   2   4`\n(με επιπλέον κενά);\n\n```c\n#include <stdio.h>\n\nint main() {\n  int n1, n2;\n  printf(\"Gimme two numbers: \");\n  scanf(\"%d %d\", &n1, &n2);\n  printf(\"Result: %d\\n\", n1 * n2);\n  return 0;\n}\n```",
  "hint": "Τι κάνει η `scanf` με τους κενούς χαρακτήρες όταν ψάχνει για δεκαδικό ψηφίο;"
 },
 {
  "id": "slides-lec11-access-by-address",
  "kind": "slides",
  "title": "Πρόσβαση σε μεταβλητή μόνο μέσω της διεύθυνσής της",
  "source": {
   "title": "Διάλεξη 11, διαφάνεια 20",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec11.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   11
  ],
  "topics": [
   "pointers"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α11.1",
  "path": "questions/slides/slides-lec11-access-by-address.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec11-access-by-address.html",
  "statement": "Ο δείκτης *δείχνει* σε μια μεταβλητή. Μπορώ να προσπελάσω τη μεταβλητή έχοντας μόνο τη\nδιεύθυνσή της;",
  "hint": "Ο `&` πάει από τη μεταβλητή στη διεύθυνση. Υπάρχει τελεστής που κάνει την αντίστροφη\nδιαδρομή; Σκεφτείτε αν η έκφραση που προκύπτει μπορεί να χρησιμοποιηθεί και για\nανάγνωση και για ανάθεση."
 },
 {
  "id": "slides-lec11-array-pointer-trace",
  "kind": "slides",
  "title": "Αναφορά σε στοιχεία πίνακα μέσω δείκτη",
  "source": {
   "title": "Διάλεξη 11, διαφάνειες 29–30",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec11.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   11
  ],
  "topics": [
   "pointer-arithmetic",
   "pointers",
   "arrays"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α11.2",
  "path": "questions/slides/slides-lec11-array-pointer-trace.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec11-array-pointer-trace.html",
  "statement": "Αναφορά σε στοιχεία πίνακα: τι θα τυπώσει;\n\n```c\n#include <stdio.h>\nint main() {\n  int *ptr, arr[] = {10, 20, 30};\n  ptr = &arr[0];\n  printf(\"mem[%p], %d\\n\", ptr, *ptr);\n  ptr += 2;\n  printf(\"mem[%p], %d\\n\", ptr, *ptr);\n  return 0;\n}\n```",
  "hint": "Τις ακριβείς διευθύνσεις δεν μπορείτε να τις ξέρετε, αλλά μπορείτε να πείτε πόσο\nδιαφέρουν οι δύο. Κατά πόσα bytes μετακινεί το `ptr += 2` έναν `int *`, και σε ποιο\nστοιχείο του πίνακα δείχνει μετά;"
 },
 {
  "id": "slides-lec11-assign-through-pointers",
  "kind": "slides",
  "title": "Αναθέσεις μέσω δεικτών",
  "source": {
   "title": "Διάλεξη 11, διαφάνεια 24",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec11.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   11
  ],
  "topics": [
   "pointers"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α11.3",
  "path": "questions/slides/slides-lec11-assign-through-pointers.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec11-assign-through-pointers.html",
  "statement": "Τι τυπώνει το παρακάτω πρόγραμμα;\n\n```c\n#include <stdio.h>\nint main() {\n  int a = 100, b = 200, c;\n  int *ptr_a = &a, *ptr_b = &b, *ptr_c = &c;\n  *ptr_c = a;\n  *ptr_a = b;\n  *ptr_b = *ptr_c;\n  printf(\"%d %d %d\", a, b, c);\n  return 0;\n}\n```",
  "hint": "Αντικαταστήστε κάθε `*ptr_x` με τη μεταβλητή στην οποία δείχνει ο δείκτης και\nεκτελέστε τις τρεις αναθέσεις με τη σειρά, κρατώντας έναν πίνακα με τις τιμές των\n`a`, `b`, `c` μετά από κάθε γραμμή."
 },
 {
  "id": "slides-lec11-atoi-pitfalls",
  "kind": "slides",
  "title": "Τι μπορεί να πάει στραβά με την atoi",
  "source": {
   "title": "Διάλεξη 11, διαφάνεια 42",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec11.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   11
  ],
  "topics": [
   "strings",
   "input-validation",
   "integer-representation"
  ],
  "difficulty": 2,
  "type": "debug",
  "label": "Α11.12",
  "path": "questions/slides/slides-lec11-atoi-pitfalls.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec11-atoi-pitfalls.html",
  "statement": "Τι μπορεί να πάει στραβά με αυτήν τη συνάρτηση;\n\n```c\nint atoi(char digits[]) {\n  int result = 0;\n  for (int i = 0; digits[i]; i++) {\n    result = 10 * result + digits[i] - '0';\n  }\n  return result;\n}\n```",
  "hint": "Δοκιμάστε νοερά εισόδους που παραβιάζουν τις υποθέσεις της: χαρακτήρες που δεν είναι\nψηφία (π.χ. πρόσημο), έναν πολύ μεγάλο αριθμό, έναν πίνακα χωρίς `'\\0'` στο τέλος.\nΣκεφτείτε επίσης αν το όνομα της συνάρτησης συγκρούεται με κάτι από την standard\nlibrary."
 },
 {
  "id": "slides-lec11-atoi",
  "kind": "slides",
  "title": "Η δική μας atoi",
  "source": {
   "title": "Διάλεξη 11, διαφάνειες 41–42",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec11.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   11,
   10
  ],
  "topics": [
   "strings",
   "arrays",
   "functions"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α11.11",
  "path": "questions/slides/slides-lec11-atoi.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec11-atoi.html",
  "statement": "Θέλω μια συνάρτηση `atoi` που να παίρνει έναν πίνακα χαρακτήρων (μόνο ψηφία) και να\nεπιστρέφει έναν ακέραιο. Πώς;",
  "hint": "Διατρέξτε τους χαρακτήρες μέχρι το `'\\0'`. Η τιμή ενός χαρακτήρα-ψηφίου προκύπτει\nαφαιρώντας του το `'0'`· σκεφτείτε πώς αλλάζει το μέχρι τώρα αποτέλεσμα όταν\n«προσθέτετε» ένα ψηφίο στα δεξιά του (π.χ. από 12 σε 123)."
 },
 {
  "id": "slides-lec11-average",
  "kind": "slides",
  "title": "Μέσος όρος πίνακα 100 ακεραίων",
  "source": {
   "title": "Διάλεξη 11, διαφάνειες 37–38",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec11.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   11,
   10
  ],
  "topics": [
   "arrays",
   "functions"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α11.4",
  "path": "questions/slides/slides-lec11-average.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec11-average.html",
  "statement": "Θέλω μια συνάρτηση που να δέχεται έναν πίνακα 100 ακεραίων και να επιστρέφει τον μέσο\nόρο. Πώς;",
  "hint": "Η παράμετρος μπορεί να δηλωθεί ως πίνακας (`int grades[100]`). Αθροίστε τα στοιχεία με\nέναν βρόχο `for` και διαιρέστε στο τέλος· σκεφτείτε αν θέλετε ακέραια διαίρεση ή\nαποτέλεσμα με δεκαδικά."
 },
 {
  "id": "slides-lec11-factorial-calls",
  "kind": "slides",
  "title": "Πόσες αναδρομικές κλήσεις κάνει το factorial",
  "source": {
   "title": "Διάλεξη 11, διαφάνεια 46",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec11.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   11
  ],
  "topics": [
   "recursion"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α11.6",
  "path": "questions/slides/slides-lec11-factorial-calls.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec11-factorial-calls.html",
  "statement": "Με τη συνάρτηση\n\n```c\nint factorial(int number) {\n  if (number == 0) return 1;\n  else return number * factorial(number - 1);\n}\n```\n\nπόσες αναδρομικές (στον εαυτό της) κλήσεις κάνει η κλήση `factorial(5)`; Πόσες η κλήση\n`factorial(N)`;",
  "hint": "Γράψτε την αλυσίδα κλήσεων που ξεκινά από το `factorial(5)` μέχρι τη βάση τερματισμού\nκαι μετρήστε τους κρίκους της, προσέχοντας αν μετράτε και την αρχική κλήση. Μετά\nγενικεύστε για `N`."
 },
 {
  "id": "slides-lec11-factorial-negative",
  "kind": "slides",
  "title": "Αρνητικό όρισμα στο αναδρομικό παραγοντικό",
  "source": {
   "title": "Διάλεξη 11, διαφάνεια 46",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec11.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   11
  ],
  "topics": [
   "recursion",
   "undefined-behavior"
  ],
  "difficulty": 2,
  "type": "short-answer",
  "label": "Α11.13",
  "path": "questions/slides/slides-lec11-factorial-negative.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec11-factorial-negative.html",
  "statement": "Τι θα συμβεί αν δώσουμε έναν αρνητικό αριθμό στη συνάρτησή μας;\n\n```c\nint factorial(int number) {\n  if (number == 0) return 1;\n  else return number * factorial(number - 1);\n}\n```",
  "hint": "Ακολουθήστε τις τιμές του `number` στις διαδοχικές κλήσεις ξεκινώντας από `-1`. Φτάνει\nποτέ στη βάση τερματισμού; Τι κοστίζει στη μνήμη κάθε κλήση που δεν έχει ακόμα\nεπιστρέψει; Πώς θα άλλαζε η συνθήκη της βάσης για να προστατεύεται η συνάρτηση;"
 },
 {
  "id": "slides-lec11-factorial-overflow",
  "kind": "slides",
  "title": "Αρνητικό παραγοντικό",
  "source": {
   "title": "Διάλεξη 11, διαφάνεια 46",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec11.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   11
  ],
  "topics": [
   "integer-representation",
   "recursion"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α11.7",
  "path": "questions/slides/slides-lec11-factorial-overflow.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec11-factorial-overflow.html",
  "statement": "Για κάποιους αριθμούς το αποτέλεσμα του αναδρομικού προγράμματος παραγοντικού (με\n`int`) είναι αρνητικό. Τι συμβαίνει;\n\n```text\n$ ./fact 20\n20! = -2102132736\n```",
  "hint": "Ποια είναι η μεγαλύτερη τιμή που χωρά σε έναν `int` των 32 bit; Υπολογίστε πρόχειρα\nπόσο γρήγορα μεγαλώνει το $n!$ και βρείτε το πρώτο $n$ για το οποίο το ξεπερνά."
 },
 {
  "id": "slides-lec11-factorial",
  "kind": "slides",
  "title": "Το παραγοντικό αναδρομικά σε C",
  "source": {
   "title": "Διάλεξη 11, διαφάνειες 44–45",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec11.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   11
  ],
  "topics": [
   "recursion",
   "functions",
   "command-line-args"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α11.5",
  "path": "questions/slides/slides-lec11-factorial.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec11-factorial.html",
  "statement": "Στα μαθηματικά το παραγοντικό ενός φυσικού αριθμού $n$, συμβολίζεται με $n!$ και είναι\nτο γινόμενο όλων των θετικών ακεραίων μικρότερων ή ίσων του $n$. Ο ορισμός του\nπαραγοντικού στα μαθηματικά είναι αναδρομικός (recursive):\n\n$$n! = 1 \\text{ if } n = 0, \\qquad n! = n \\times (n-1)! \\text{ if } n > 0$$\n\nΠώς θα το γράφαμε σε C; Το πρόγραμμα παίρνει τον αριθμό από τη γραμμή εντολών:\n\n```text\n$ ./fact 5\n5! = 120\n```",
  "hint": "Οι δύο γραμμές του ορισμού αντιστοιχούν στις δύο περιπτώσεις μιας αναδρομικής\nσυνάρτησης: η πρώτη είναι η βάση τερματισμού, η δεύτερη η κλήση της συνάρτησης στον\nεαυτό της με μικρότερο όρισμα. Για την είσοδο, μετατρέψτε το `argv[1]` σε ακέραιο με\nτην `atoi`."
 },
 {
  "id": "slides-lec11-find",
  "kind": "slides",
  "title": "Θέση στοιχείου σε πίνακα ή -1",
  "source": {
   "title": "Διάλεξη 11, διαφάνειες 39–40",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec11.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   11,
   10
  ],
  "topics": [
   "arrays",
   "functions",
   "searching"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α11.8",
  "path": "questions/slides/slides-lec11-find.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec11-find.html",
  "statement": "Θέλω μια συνάρτηση που να δέχεται έναν πίνακα 100 ακεραίων και έναν ακέραιο και να\nγυρνάει τη θέση του στοιχείου αν το βρήκε ή `-1`. Πώς;",
  "hint": "Διατρέξτε τον πίνακα από την αρχή· μόλις βρείτε το στοιχείο μπορείτε να επιστρέψετε\nαμέσως από μέσα από τον βρόχο. Τι πρέπει να γίνει αν ο βρόχος τελειώσει χωρίς να το\nβρει;"
 },
 {
  "id": "slides-lec11-pointer-sizes",
  "kind": "slides",
  "title": "Το μέγεθος δεικτών διαφορετικών τύπων",
  "source": {
   "title": "Διάλεξη 11, διαφάνεια 18",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec11.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   11
  ],
  "topics": [
   "pointers",
   "types"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α11.9",
  "path": "questions/slides/slides-lec11-pointer-sizes.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec11-pointer-sizes.html",
  "statement": "Τι θα τυπώσει το παρακάτω πρόγραμμα;\n\n```c\n#include <stdio.h>\n\nint main() {\n  int * ipointer;\n  char * cpointer;\n  double * dpointer;\n  printf(\"%d %d %d\\n\", sizeof(ipointer), sizeof(cpointer), sizeof(dpointer));\n  return 0;\n}\n```",
  "hint": "Τι ακριβώς αποθηκεύει μια μεταβλητή τύπου δείκτη; Εξαρτάται το μέγεθος αυτού που\nαποθηκεύει από τον τύπο των δεδομένων στα οποία δείχνει ή από το σύστημα (32 ή 64 bit)\nγια το οποίο μεταγλωττίζεται το πρόγραμμα;"
 },
 {
  "id": "slides-lec11-print-world",
  "kind": "slides",
  "title": "Πώς τυπώνω μόνο το World",
  "source": {
   "title": "Διάλεξη 11, διαφάνειες 34–35",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec11.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   11
  ],
  "topics": [
   "pointers",
   "strings",
   "arrays"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α11.10",
  "path": "questions/slides/slides-lec11-print-world.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec11-print-world.html",
  "statement": "Από την προηγούμενη φορά, πώς μπορώ να τυπώσω `\"World\\n\"`; Συμπληρώστε το `...`:\n\n```c\nchar hello[] = \"Hello World\\n\";\nchar *world = ...;\nprintf(\"%s\", world);\n```",
  "hint": "Το `%s` τυπώνει χαρακτήρες ξεκινώντας από τη διεύθυνση που του δίνετε, μέχρι το\n`'\\0'`. Μετρήστε σε ποια θέση του πίνακα βρίσκεται το `'W'` και σκεφτείτε πώς\nπαίρνετε τη διεύθυνση αυτού του στοιχείου."
 },
 {
  "id": "slides-lec12-2d-element",
  "kind": "slides",
  "title": "Στοιχείο δισδιάστατου πίνακα",
  "source": {
   "title": "Διάλεξη 12, διαφάνεια 14",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec12.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   12
  ],
  "topics": [
   "multidim-arrays",
   "arrays"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α12.1",
  "path": "questions/slides/slides-lec12-2d-element.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec12-2d-element.html",
  "statement": "Δίνεται ο πίνακας:\n\n```c\nint array[2][4] = {\n    {1, 4, 7, 10},\n    {3, 6, 9, 12},\n};\n```\n\nΠοιο είναι το στοιχείο `a[1][1]` (δηλαδή `array[1][1]`);",
  "hint": "Ο πρώτος δείκτης επιλέγει τη γραμμή και ο δεύτερος τη στήλη, και οι δύο μετρούν από\nτο 0. Γράψτε τον πίνακα σε μορφή γραμμών και στηλών και βρείτε το κελί."
 },
 {
  "id": "slides-lec12-array-of-pointers",
  "kind": "slides",
  "title": "Πίνακας από δείκτες",
  "source": {
   "title": "Διάλεξη 12, διαφάνεια 29",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec12.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   12
  ],
  "topics": [
   "pointers",
   "arrays"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α12.2",
  "path": "questions/slides/slides-lec12-array-of-pointers.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec12-array-of-pointers.html",
  "statement": "Οι δείκτες είναι μεταβλητές και μπορούν να μπουν σε πίνακες. Για παράδειγμα, τι θα\nτυπώσει το ακόλουθο;\n\n```c\n#include <stdio.h>\nint main() {\n  int *ptr[3], a = 100, b = 200, c = 300;\n  ptr[0] = &a;\n  ptr[1] = &b;\n  ptr[2] = &c;\n  printf(\"%d %d %d\\n\", *ptr[2], *ptr[1], *ptr[0]);\n  return 0;\n}\n```",
  "hint": "Το `*ptr[2]` διαβάζεται ως `*(ptr[2])`: πρώτα παίρνουμε το στοιχείο του πίνακα\n(έναν δείκτη) και μετά την τιμή όπου αυτός δείχνει. Προσέξτε τη σειρά των ορισμάτων\nστο `printf`."
 },
 {
  "id": "slides-lec12-endianness",
  "kind": "slides",
  "title": "Παράδειγμα endianness",
  "source": {
   "title": "Διάλεξη 12, διαφάνεια 42",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec12.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   12,
   13
  ],
  "topics": [
   "memory-model",
   "pointers",
   "integer-representation"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α12.4",
  "path": "questions/slides/slides-lec12-endianness.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec12-endianness.html",
  "statement": "Τι θα τυπώσει το παρακάτω;\n\n```c\n#include <stdio.h>\nint main() {\n  int x = 42;\n  char * bytes = (char*)&x;\n  int i;\n  for(i = 0; i < sizeof(int) / sizeof(char); i++)\n     printf(\"%02x\\n\", bytes[i]);\n  return 0;\n}\n```",
  "hint": "Γράψτε το 42 σε δεκαεξαδικό ως ακέραιο 4 bytes. Ο δείκτης `bytes` διατρέχει τη μνήμη\nτου `x` ένα byte τη φορά, από τη χαμηλότερη διεύθυνση· η απάντηση εξαρτάται από το αν\nο υπολογιστής σας είναι little ή big endian (οι x86 και οι περισσότεροι ARM είναι\nlittle endian)."
 },
 {
  "id": "slides-lec12-malloc-sizeof",
  "kind": "slides",
  "title": "Πόση μνήμη δεσμεύει η malloc και τι λέει το sizeof",
  "source": {
   "title": "Διάλεξη 12, διαφάνειες 39–40",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec12.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   12,
   13
  ],
  "topics": [
   "dynamic-memory",
   "pointers",
   "types"
  ],
  "difficulty": 2,
  "type": "short-answer",
  "label": "Α12.5",
  "path": "questions/slides/slides-lec12-malloc-sizeof.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec12-malloc-sizeof.html",
  "statement": "```c\nint * nums = malloc(100 * sizeof(int));\ndouble * coeffs = malloc(100 * sizeof(double));\nchar * str = malloc(100 * sizeof(char));\n```\n\n1. Πόση μνήμη δεσμεύεται με καθεμιά από τις παραπάνω κλήσεις;\n2. Τι θα τυπώσει το ακόλουθο;\n\n```c\nprintf(\"%d %d %d\\n\", sizeof(nums), sizeof(coeffs), sizeof(str));\n```",
  "hint": "Για το (1), η `malloc` μετρά bytes: υπολογίστε `100 * sizeof(τύπος)` με τα\nσυνηθισμένα μεγέθη των τύπων. Για το (2), αναρωτηθείτε ποιος είναι ο τύπος των\n`nums`, `coeffs` και `str`: πίνακες ή δείκτες; Και τι μέγεθος έχει μια διεύθυνση\nσε ένα σύστημα 64 bit;"
 },
 {
  "id": "slides-lec12-multidim-necessary",
  "kind": "slides",
  "title": "Είναι απαραίτητοι οι πολυδιάστατοι πίνακες;",
  "source": {
   "title": "Διάλεξη 12, διαφάνεια 23",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec12.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   12
  ],
  "topics": [
   "multidim-arrays",
   "arrays",
   "memory-model"
  ],
  "difficulty": 2,
  "type": "short-answer",
  "label": "Α12.6",
  "path": "questions/slides/slides-lec12-multidim-necessary.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec12-multidim-necessary.html",
  "statement": "Πίνακες υψηλότερων διαστάσεων λειτουργούν με τον ίδιο τρόπο, προσθέτοντας τον\nεπιθυμητό αριθμό διαστάσεων, π.χ. ένας κύβος του Rubik:\n\n```c\nint rubiksCube[6][3][3] = {\n    {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, // Face 1 (e.g., Red)\n    {{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, // Face 2 (e.g., Green)\n    {{2, 2, 2}, {2, 2, 2}, {2, 2, 2}}, // Face 3 (e.g., Blue)\n    {{3, 3, 3}, {3, 3, 3}, {3, 3, 3}}, // Face 4 (e.g., Yellow)\n    {{4, 4, 4}, {4, 4, 4}, {4, 4, 4}}, // Face 5 (e.g., Orange)\n    {{5, 5, 5}, {5, 5, 5}, {5, 5, 5}}  // Face 6 (e.g., White)\n};\n```\n\nΕίναι απαραίτητοι οι πολυδιάστατοι πίνακες;",
  "hint": "Θυμηθείτε πώς αποθηκεύεται ένας δισδιάστατος πίνακας στη μνήμη και τον τύπο\n`i * Y + j` για τη θέση του `a[i][j]`. Τι θα χρειαζόταν για να κρατήσετε τα ίδια\nδεδομένα σε έναν μονοδιάστατο πίνακα, και τι κερδίζετε όταν τον λογαριασμό τον κάνει\nο μεταγλωττιστής;"
 },
 {
  "id": "slides-lec12-pointer-copy-loop",
  "kind": "slides",
  "title": "Περιεχόμενα του x μετά από βρόχο με δείκτη",
  "source": {
   "title": "Διάλεξη 12, διαφάνεια 25",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec12.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   12,
   11
  ],
  "topics": [
   "pointer-arithmetic",
   "pointers",
   "arrays"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α12.7",
  "path": "questions/slides/slides-lec12-pointer-copy-loop.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec12-pointer-copy-loop.html",
  "statement": "Ποια είναι τα περιεχόμενα του `x` μετά την εκτέλεση;\n\n```c\nint * p;\nint x[] = {5, 7, 2, 3, 6, 0, 1, 4};\np = x;\nwhile (*p = *(p+2))\n  p++;\n```",
  "hint": "Η συνθήκη του `while` είναι ανάθεση, όχι σύγκριση: αντιγράφει στο `*p` την τιμή\nδύο θέσεις πιο μετά, και ο βρόχος σταματά όταν η τιμή που αντιγράφηκε είναι 0.\nΙχνηλατήστε βήμα-βήμα σε πίνακα τη θέση του `p` και τα περιεχόμενα του `x`,\nθυμίζοντας στον εαυτό σας ότι ο πίνακας αλλάζει καθώς προχωρά ο βρόχος."
 },
 {
  "id": "slides-lec12-pointer-to-pointer",
  "kind": "slides",
  "title": "Δείκτης σε δείκτη",
  "source": {
   "title": "Διάλεξη 12, διαφάνεια 27",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec12.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   12
  ],
  "topics": [
   "pointers",
   "memory-model"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α12.3",
  "path": "questions/slides/slides-lec12-pointer-to-pointer.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec12-pointer-to-pointer.html",
  "statement": "Τι θα τυπώσει το παρακάτω;\n\n```c\nint x = 42;\nint * ptr = &x;\nint ** ptr2 = &ptr;\nprintf(\"%p %d\", *ptr2, **ptr2);\n```\n\nΣτη διαφάνεια η μνήμη σχεδιάζεται ως εξής: το `x` βρίσκεται στη διεύθυνση 100 με\nτιμή 42, ο `ptr` στη διεύθυνση 200 με τιμή 100, και ο `ptr2` στη διεύθυνση 400 με\nτιμή 200.",
  "hint": "Κάθε `*` «ακολουθεί ένα βέλος»: ξεκινήστε από την τιμή του `ptr2` και βρείτε τι\nυπάρχει στη διεύθυνση όπου δείχνει, μία φορά για το `*ptr2` και δύο φορές για το\n`**ptr2`. Σκεφτείτε επίσης σε τι μορφή τυπώνει το `%p`."
 },
 {
  "id": "slides-lec13-after-free",
  "kind": "slides",
  "title": "Τι γίνεται μετά την free;",
  "source": {
   "title": "Διάλεξη 13, διαφάνειες 47–51",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec13.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   13
  ],
  "topics": [
   "dynamic-memory",
   "undefined-behavior"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α13.1",
  "path": "questions/slides/slides-lec13-after-free.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec13-after-free.html",
  "statement": "Μάθαμε να δεσμεύουμε μνήμη με την `malloc`: μας λείπει κάτι;\n\n```c\nint * array = malloc(4 * sizeof(int));\nif (!array) {\n  // fail gracefully\n}\nfree(array);\n```\n\n1. Τι θα συμβεί στη μνήμη (στη στοίβα και στον σωρό) μετά την `free`;\n2. Τι θα συμβεί αν προσπαθήσουμε να προσπελάσουμε μνήμη που έχουμε αποδεσμεύσει,\n   π.χ. με `array[0] = 4;` μετά την `free`;\n3. Τι θα συμβεί αν προσπαθήσουμε να αποδεσμεύσουμε μνήμη που έχουμε ήδη αποδεσμεύσει,\n   δηλαδή με δεύτερο `free(array);`;",
  "hint": "Ξεχωρίστε τον pointer `array` (που ζει στη στοίβα) από το μπλοκ στο οποίο δείχνει\n(στον σωρό): ποιο από τα δύο αλλάζει η `free`; Για τα 2 και 3, σκεφτείτε τι\nσημαίνει να χρησιμοποιούμε μνήμη που δεν μας ανήκει πια, στην καλύτερη και στη\nχειρότερη περίπτωση."
 },
 {
  "id": "slides-lec13-dynamic-2d",
  "kind": "slides",
  "title": "Δυναμικός δισδιάστατος πίνακας MxN",
  "source": {
   "title": "Διάλεξη 13, διαφάνειες 56–58",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec13.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   13,
   12
  ],
  "topics": [
   "dynamic-memory",
   "multidim-arrays",
   "pointers"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α13.4",
  "path": "questions/slides/slides-lec13-dynamic-2d.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec13-dynamic-2d.html",
  "statement": "Θέλω να δημιουργήσω έναν δισδιάστατο πίνακα ακεραίων `M`x`N` δυναμικά. Πώς;\nΘέλω μετά να αποδεσμεύσω τη μνήμη του. Πώς;\n\nΓράψτε τον κώδικα και για τα δύο, ώστε μετά τη δέσμευση να μπορείτε να γράφετε\n`array[i][j]` όπως σε έναν στατικό πίνακα. Για `M = 5`, `N = 6` και τον πίνακα\nγεμάτο με 1, 2, 3, … γραμμή-γραμμή, το `array[1][3]` πρέπει να είναι 10 και το\n`array[2][2]` 15.",
  "hint": "Ο `array` είναι `int **`: δεσμεύστε πρώτα έναν πίνακα από `M` pointers και μετά μία\nγραμμή των `N` ακεραίων για καθέναν, ελέγχοντας κάθε κλήση για `NULL`. Για την\nαποδέσμευση σκεφτείτε τη σειρά: τι χάνετε αν αποδεσμεύσετε πρώτα τον πίνακα των\npointers;"
 },
 {
  "id": "slides-lec13-heap-bomb",
  "kind": "slides",
  "title": "Ένας τεράστιος πίνακας στον σωρό",
  "source": {
   "title": "Διάλεξη 13, διαφάνειες 43–46",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec13.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   13
  ],
  "topics": [
   "dynamic-memory",
   "memory-model"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α13.5",
  "path": "questions/slides/slides-lec13-heap-bomb.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec13-heap-bomb.html",
  "statement": "Τι θα κάνει το ακόλουθο πρόγραμμα;\n\n```c\n#include <stdio.h>\n#include <stdlib.h>\nint main() {\n  char *bomb = malloc(sizeof(char) * 9000000);\n  printf(\"Hello World\\n\");\n  return 0;\n}\n```\n\nΤι θα κάνει αν η `malloc` ζητήσει `sizeof(char) * 900000000000L` bytes; Και τι αν\nμετά από αυτή την κλήση προσθέσουμε τη γραμμή `bomb[0] = 'A';` πριν το `printf`;\nΠώς πρέπει να διορθωθεί το πρόγραμμα;",
  "hint": "Συγκρίνετε κάθε μέγεθος με τη μνήμη του υπολογιστή σας. Τι επιστρέφει η `malloc`\nόταν δεν υπάρχει αρκετή μνήμη, και τι γίνεται όταν γράφουμε σε αυτή τη διεύθυνση;"
 },
 {
  "id": "slides-lec13-infinite-recursion",
  "kind": "slides",
  "title": "Γιατί η αναδρομή πρέπει να τελειώνει;",
  "source": {
   "title": "Διάλεξη 13, διαφάνεια 27",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec13.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   13,
   11
  ],
  "topics": [
   "recursion",
   "memory-model"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α13.2",
  "path": "questions/slides/slides-lec13-infinite-recursion.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec13-infinite-recursion.html",
  "statement": "Είχαμε πει «η αναδρομή πρέπει να τελειώνει». Γιατί;\n\n```c\nvoid recurse() {\n  recurse();\n}\n\nint main() {\n  recurse();\n  return 0;\n}\n```\n\n```text\n$ gcc -o rec rec.c\n$ ./rec\nSegmentation fault\n```",
  "hint": "Σκεφτείτε τι μπαίνει στη στοίβα σε κάθε κλήση της `recurse` και πότε αφαιρείται.\nΗ στοίβα έχει πεπερασμένο μέγεθος (δείτε `ulimit -s`)."
 },
 {
  "id": "slides-lec13-quiz-5x5",
  "kind": "slides",
  "title": "Κουίζ: πίνακας 5x5 σε συνάρτηση",
  "source": {
   "title": "Διάλεξη 13, διαφάνειες 61–63",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec13.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   13
  ],
  "topics": [
   "dynamic-memory",
   "multidim-arrays",
   "good-practice"
  ],
  "difficulty": 2,
  "type": "debug",
  "label": "Α13.6",
  "path": "questions/slides/slides-lec13-quiz-5x5.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec13-quiz-5x5.html",
  "statement": "Θέλω να δημιουργήσω έναν πίνακα 5x5. Για καθεμία από τις τρεις υλοποιήσεις, είναι\nσωστή; Αν όχι, τι πρόβλημα έχει;\n\n**Υλοποίηση 1**\n\n```c\nvoid bar() {\n  int ** array = malloc(5 * sizeof(int*));\n  int i;\n  for(i = 0 ; i < 5 ; i++)\n    array[i] = malloc(5 * sizeof(int));\n  // process loop here\n}\n```\n\n**Υλοποίηση 2**\n\n```c\nvoid bar() {\n  int ** array = malloc(5 * sizeof(int*));\n  if (!array) {\n    return;\n  }\n  int i;\n  for(i = 0 ; i < 5 ; i++) {\n    array[i] = malloc(5 * sizeof(int));\n    if (!array[i]) {\n      return;\n    }\n  }\n  // process loop here\n}\n```\n\n**Υλοποίηση 3**\n\n```c\nvoid bar() {\n  int ** array = malloc(5 * sizeof(int*));\n  if (!array) {\n    return;\n  }\n  int i;\n  for(i = 0 ; i < 5 ; i++) {\n    array[i] = malloc(5 * sizeof(int));\n    if (!array[i]) {\n      return;\n    }\n  }\n  // process loop here\n  for(i = 0 ; i < 5 ; i++) {\n    free(array[i]);\n  }\n  free(array);\n}\n```",
  "hint": "Για κάθε `malloc` ρωτήστε: ελέγχεται για `NULL`; Αποδεσμεύεται με `free` σε\n**κάθε** δρόμο εξόδου από τη συνάρτηση, και στον κανονικό και σε αυτόν μιας\nαποτυχίας στη μέση του βρόχου;"
 },
 {
  "id": "slides-lec13-stack-bomb",
  "kind": "slides",
  "title": "Ένας τεράστιος πίνακας στη στοίβα",
  "source": {
   "title": "Διάλεξη 13, διαφάνειες 28–31",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec13.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   13
  ],
  "topics": [
   "memory-model",
   "arrays",
   "dynamic-memory"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α13.7",
  "path": "questions/slides/slides-lec13-stack-bomb.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec13-stack-bomb.html",
  "statement": "Τι θα κάνει το ακόλουθο πρόγραμμα;\n\n```c\n#include <stdio.h>\n\nint main() {\n  char bomb[9000000];\n  printf(\"Hello World\\n\");\n  return 0;\n}\n```\n\n```text\n$ ulimit -s\n8192\n```\n\nΤι αλλάζει αν πρώτα εκτελέσουμε `ulimit -s unlimited`; Και τι κάνουμε όταν η στοίβα\nδεν είναι αρκετή και χρειάζεται να χρησιμοποιήσουμε πίνακες μεγάλου μεγέθους;",
  "hint": "Η τιμή του `ulimit -s` είναι σε KB. Συγκρίνετε τη με το μέγεθος του τοπικού πίνακα\nκαι θυμηθείτε πού αποθηκεύονται οι τοπικές μεταβλητές. Για το τελευταίο ερώτημα,\nσκεφτείτε ποια άλλη κατηγορία μνήμης μπορεί να δεσμεύσει όλη τη διαθέσιμη μνήμη."
 },
 {
  "id": "slides-lec13-stack-frames",
  "kind": "slides",
  "title": "Τα stack frames της equalIgnoreCase",
  "source": {
   "title": "Διάλεξη 13, διαφάνειες 20–26",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec13.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   13
  ],
  "topics": [
   "memory-model",
   "functions"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α13.3",
  "path": "questions/slides/slides-lec13-stack-frames.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec13-stack-frames.html",
  "statement": "```c\nchar tolower(char c) {\n    if (c >= 'A' && c <= 'Z')\n        return c + ('a' - 'A');\n    return c;\n}\nint equalIgnoreCase(char char1, char char2) {\n    char lowerChar1 = tolower(char1);\n    char lowerChar2 = tolower(char2);\n    return lowerChar1 == lowerChar2;\n}\n```\n\nΗ εκτέλεση βρίσκεται μέσα στην `equalIgnoreCase`, και η στοίβα περιέχει το stack\nframe της (`char1`, `char2`, `lowerChar1`, `lowerChar2` και προσωρινά δεδομένα του\nμεταγλωττιστή).\n\n1. Τι θα συμβεί όταν κληθεί η συνάρτηση `tolower` την πρώτη φορά;\n2. Τι θα συμβεί όταν εκτελεστεί η εντολή `return` (της `tolower`);\n3. Τι θα συμβεί όταν εκτελεστεί η δεύτερη κλήση `tolower`;\n4. Τι θα συμβεί όταν εκτελεστεί η `return` της `equalIgnoreCase`;",
  "hint": "Θυμηθείτε ότι η στοίβα λειτουργεί με σειρά LIFO και ότι κάθε κλήση συνάρτησης\nπαίρνει το δικό της activation record με τα ορίσματα, τις τοπικές μεταβλητές και\nπροσωρινά δεδομένα. Σχεδιάστε τη στοίβα ως κουτάκια μετά από κάθε βήμα."
 },
 {
  "id": "slides-lec14-check-boo",
  "kind": "slides",
  "title": "Είναι το πρώτο όρισμα \"--boo\";",
  "source": {
   "title": "Διάλεξη 14, διαφάνεια 42",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec14.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   14,
   12
  ],
  "topics": [
   "strings",
   "command-line-args"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α14.1",
  "path": "questions/slides/slides-lec14-check-boo.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec14-check-boo.html",
  "statement": "Θέλω να ελέγξω αν το πρώτο όρισμα του προγράμματός μου είναι `\"--boo\"`. Πώς;",
  "hint": "Το πρώτο όρισμα είναι το `argv[1]`, αλλά υπάρχει μόνο αν το `argc` είναι αρκετά\nμεγάλο. Ο τελεστής `==` σε δύο string συγκρίνει διευθύνσεις, όχι περιεχόμενα·\nχρειάζεστε μια συνάρτηση της `string.h` και να θυμάστε τι επιστρέφει όταν τα string\nείναι ίσα."
 },
 {
  "id": "slides-lec14-local-param",
  "kind": "slides",
  "title": "Αύξηση παραμέτρου μέσα σε συνάρτηση",
  "source": {
   "title": "Διάλεξη 14, διαφάνειες 11–12",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec14.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   14,
   3
  ],
  "topics": [
   "scope",
   "functions"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α14.2",
  "path": "questions/slides/slides-lec14-local-param.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec14-local-param.html",
  "statement": "Τι θα επιστρέψει αυτό το πρόγραμμα;\n\n```c\nvoid foo(int i) {\n  i++;\n}\nint main() {\n  int i = 42;\n  foo(i);\n  return i;\n}\n```\n\n```text\n$ gcc -o local2 local2.c\n$ ./local2\n$ echo $?\n```",
  "hint": "Η παράμετρος μιας συνάρτησης είναι κι αυτή τοπική μεταβλητή, που αρχικοποιείται\nκατά την κλήση με την τιμή του ορίσματος. Σκεφτείτε ποια μεταβλητή αυξάνει το `i++`\nκαι ποια επιστρέφει η `main`."
 },
 {
  "id": "slides-lec14-local-same-name",
  "kind": "slides",
  "title": "Τοπική μεταβλητή με το ίδιο όνομα σε δύο συναρτήσεις",
  "source": {
   "title": "Διάλεξη 14, διαφάνειες 9–10",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec14.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   14
  ],
  "topics": [
   "scope",
   "functions"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α14.3",
  "path": "questions/slides/slides-lec14-local-same-name.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec14-local-same-name.html",
  "statement": "Η τοπική μεταβλητή μιας συνάρτησης δεν είναι ορατή σε κάποια άλλη συνάρτηση και\nεπομένως μπορούμε να δηλώσουμε μεταβλητές με το ίδιο όνομα σε άλλες συναρτήσεις και\nνα αναφέρονται σε άλλες θέσεις μνήμης.\n\nΤι θα επιστρέψει αυτό το πρόγραμμα;\n\n```c\nvoid foo() {\n  int i = 43;\n}\nint main() {\n  int i = 42;\n  foo();\n  return i;\n}\n```\n\n```text\n$ gcc -o local local.c\n$ ./local\n$ echo $?\n```",
  "hint": "Αναρωτηθείτε αν το `i` της `foo` και το `i` της `main` είναι η ίδια μεταβλητή:\nπού είναι η εμβέλεια του καθενός και σε ποιο frame της στοίβας ζει; Θυμηθείτε ότι το\n`echo $?` τυπώνει την τιμή που επέστρεψε η `main`."
 },
 {
  "id": "slides-lec14-palindrome",
  "kind": "slides",
  "title": "Παλινδρομικό string",
  "source": {
   "title": "Διάλεξη 14, διαφάνειες 43–44",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec14.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   14
  ],
  "topics": [
   "strings",
   "arrays"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α14.4",
  "path": "questions/slides/slides-lec14-palindrome.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec14-palindrome.html",
  "statement": "Θέλω να ελέγξω αν ένα string είναι παλινδρομικό. Πώς;\n\nΓράψτε μια συνάρτηση `int isPalindrome(char *str)` που επιστρέφει 1 αν το `str`\nδιαβάζεται ίδιο από την αρχή και από το τέλος, και 0 αλλιώς.",
  "hint": "Χρησιμοποιήστε δύο δείκτες θέσης που ξεκινούν από τις δύο άκρες του string και\nκινούνται ο ένας προς τον άλλο. Προσέξτε πού είναι ο τελευταίος χαρακτήρας: το\n`strlen` δεν μετρά το null byte."
 },
 {
  "id": "slides-lec14-shadowing",
  "kind": "slides",
  "title": "Επισκίαση παγκόσμιας μεταβλητής",
  "source": {
   "title": "Διάλεξη 14, διαφάνειες 14–16",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec14.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   14
  ],
  "topics": [
   "scope"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α14.5",
  "path": "questions/slides/slides-lec14-shadowing.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec14-shadowing.html",
  "statement": "Όταν μια δήλωση μεταβλητής βρίσκεται εντός εμβέλειας άλλης μεταβλητής με το ίδιο\nόνομα, τότε η εσωτερική μεταβλητή επισκιάζει (shadows) την άλλη. Τι θα τυπώσει;\n\n```c\n#include <stdio.h>\nint baz = 42;\nint main() {\n  int baz = 43;\n  printf(\"baz: %d\\n\", baz);\n  return 0;\n}\n```",
  "hint": "Βρείτε την εμβέλεια της παγκόσμιας `baz` και της τοπικής `baz` της `main`. Στο\nσημείο της `printf` είναι ορατές και οι δύο· ποια δήλωση είναι η πιο «εσωτερική»;"
 },
 {
  "id": "slides-lec14-static-assign",
  "kind": "slides",
  "title": "Στατική μεταβλητή με ανάθεση εκτός δήλωσης",
  "source": {
   "title": "Διάλεξη 14, διαφάνεια 19",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec14.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   14
  ],
  "topics": [
   "scope",
   "memory-model"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α14.7",
  "path": "questions/slides/slides-lec14-static-assign.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec14-static-assign.html",
  "statement": "Τι θα τυπώσει το πρόγραμμα, όπου η `counter` είναι στατική αλλά παίρνει την τιμή 0\nμε ξεχωριστή εντολή;\n\n```c\n#include <stdio.h>\nvoid foo() {\n  static int counter; int i = 0; counter = 0;\n  counter++; i++;\n  printf(\"%d %d\\n\", counter, i);\n}\nint main() {\n  foo(); foo(); foo();\n  return 0;\n}\n```",
  "hint": "Συγκρίνετε με την εκδοχή όπου το `= 0` είναι μέρος της δήλωσης\n`static int counter = 0;`. Μια αρχικοποίηση στη δήλωση μιας στατικής μεταβλητής\nγίνεται μία φορά· μια εντολή ανάθεσης όμως εκτελείται κάθε φορά που τη φτάνει η ροή."
 },
 {
  "id": "slides-lec14-static-counter",
  "kind": "slides",
  "title": "Στατική και τοπική μεταβλητή σε τρεις κλήσεις",
  "source": {
   "title": "Διάλεξη 14, διαφάνειες 17–18",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec14.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   14
  ],
  "topics": [
   "scope",
   "memory-model"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α14.6",
  "path": "questions/slides/slides-lec14-static-counter.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec14-static-counter.html",
  "statement": "Μια μεταβλητή λέγεται στατική (static), όταν διατηρεί την τιμή της ανάμεσα σε\nκλήσεις συναρτήσεων μέχρι το τέλος του προγράμματος. Οι στατικές μεταβλητές\nαρχικοποιούνται μόνο στην πρώτη κλήση της συνάρτησης. Τι θα τυπώσει;\n\n```c\n#include <stdio.h>\nvoid foo() {\n  static int counter = 0; int i = 0;\n  counter++; i++;\n  printf(\"%d %d\\n\", counter, i);\n}\nint main() {\n  foo(); foo(); foo();\n  return 0;\n}\n```",
  "hint": "Κρατήστε δύο στήλες, μία για το `counter` και μία για το `i`, και ενημερώστε τις σε\nκάθε κλήση. Ποια από τις δύο αρχικοποιήσεις εκτελείται ξανά σε κάθε κλήση και ποια\nμόνο μία φορά;"
 },
 {
  "id": "slides-lec14-str-plus-plus",
  "kind": "slides",
  "title": "Η έκφραση *str++",
  "source": {
   "title": "Διάλεξη 14, διαφάνεια 34",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec14.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   14,
   5
  ],
  "topics": [
   "pointers",
   "pointer-arithmetic",
   "precedence"
  ],
  "difficulty": 2,
  "type": "short-answer",
  "label": "Α14.8",
  "path": "questions/slides/slides-lec14-str-plus-plus.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec14-str-plus-plus.html",
  "statement": "Η υλοποίηση της `strlen` στις διαφάνειες είναι:\n\n```c\nsize_t strlen(char * str) {\n  size_t length = 0;\n  while(*str++) length++;\n  return length;\n}\n```\n\nΠώς αποτιμάται η έκφραση `*str++`;\n\n- Έχει διαφορά από την έκφραση `(*str)++`;\n- Έχει διαφορά από την έκφραση `*(str++)`;\n- Τελικά έχει σημασία η προτεραιότητα τελεστών / χρήση παρενθέσεων;",
  "hint": "Βρείτε στον πίνακα προτεραιότητας ποιος τελεστής δένει πιο σφιχτά, ο μεταθεματικός\n`++` ή το μοναδιαίο `*`. Για κάθε έκφραση απαντήστε σε δύο ερωτήσεις: ποια τιμή\nδίνει, και τι αλλάζει στη μνήμη, ο δείκτης ή ο χαρακτήρας όπου δείχνει;"
 },
 {
  "id": "slides-lec15-complexity-atoi",
  "kind": "slides",
  "title": "Πολυπλοκότητα της atoi",
  "source": {
   "title": "Διάλεξη 15, διαφάνεια 15",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec15.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   15,
   10
  ],
  "topics": [
   "complexity",
   "strings",
   "loops"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α15.1",
  "path": "questions/slides/slides-lec15-complexity-atoi.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec15-complexity-atoi.html",
  "statement": "Θέλω μια συνάρτηση `atoi` που να παίρνει ένα πίνακα χαρακτήρων (μόνο ψηφία) και να\nεπιστρέφει έναν ακέραιο. Πώς;\n\n```c\nint atoi(char digits[]) {\n  int result = 0;\n  for(int i = 0; digits[i]; i++) {\n    result = 10 * result + digits[i] - '0';\n  }\n  return result;\n}\n```\n\nΤι χρονική και τι χωρική πολυπλοκότητα έχει η συνάρτηση;",
  "hint": "Ορίστε πρώτα τι είναι το μέγεθος $N$ της εισόδου εδώ (τι ακριβώς διατρέχει ο βρόχος;).\nΜετά μετρήστε τις επαναλήψεις και τις μεταβλητές που χρειάζονται."
 },
 {
  "id": "slides-lec15-complexity-factorial",
  "kind": "slides",
  "title": "Πολυπλοκότητα του αναδρομικού παραγοντικού",
  "source": {
   "title": "Διάλεξη 15, διαφάνεια 25",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec15.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   15,
   11
  ],
  "topics": [
   "complexity",
   "recursion"
  ],
  "difficulty": 2,
  "type": "short-answer",
  "label": "Α15.10",
  "path": "questions/slides/slides-lec15-complexity-factorial.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec15-complexity-factorial.html",
  "statement": "Η συνάρτηση παραγοντικό (factorial). Τι χρονική και τι χωρική πολυπλοκότητα έχει;\n\n```c\nint factorial(int n) {\n  if (n == 0) return 1;\n  return n * factorial(n - 1);\n}\n```",
  "hint": "Για τον χρόνο, μετρήστε τις κλήσεις. Για τον χώρο, μην κοιτάξετε μόνο τις μεταβλητές\nμιας κλήσης: πόσες κλήσεις είναι ενεργές ταυτόχρονα στη στοίβα;"
 },
 {
  "id": "slides-lec15-complexity-fibonacci",
  "kind": "slides",
  "title": "Πολυπλοκότητα του αναδρομικού Fibonacci",
  "source": {
   "title": "Διάλεξη 15, διαφάνεια 27",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec15.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   15,
   11
  ],
  "topics": [
   "complexity",
   "recursion"
  ],
  "difficulty": 2,
  "type": "short-answer",
  "label": "Α15.11",
  "path": "questions/slides/slides-lec15-complexity-fibonacci.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec15-complexity-fibonacci.html",
  "statement": "Η συνάρτηση fibonacci. Τι χρονική και τι χωρική πολυπλοκότητα έχει;\n\n```c\nint fib(int n) {\n  if (n == 0 || n == 1) return 1;\n  return fib(n - 1) + fib(n - 2);\n}\n```",
  "hint": "Σχεδιάστε το δέντρο κλήσεων του `fib(4)` ή του `fib(5)`: πόσα παιδιά έχει κάθε κόμβος\nκαι πόσο βαθύ είναι το δέντρο; Ο χρόνος εξαρτάται από το πλήθος των κόμβων, ο χώρος από\nτο μακρύτερο μονοπάτι."
 },
 {
  "id": "slides-lec15-complexity-find-max-2d",
  "kind": "slides",
  "title": "Πολυπλοκότητα εύρεσης μέγιστου σε πίνακα N x N",
  "source": {
   "title": "Διάλεξη 15, διαφάνεια 23",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec15.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   15,
   12
  ],
  "topics": [
   "complexity",
   "multidim-arrays",
   "loops"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α15.2",
  "path": "questions/slides/slides-lec15-complexity-find-max-2d.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec15-complexity-find-max-2d.html",
  "statement": "Εύρεση Μέγιστου Στοιχείου σε Πίνακα N x N. Τι χρονική και τι χωρική πολυπλοκότητα\nέχει η συνάρτηση;\n\n```c\nint find_max(int **matrix, size_t n) {\n  int i, j, max = -1;\n  for(i = 0; i < n; i++) {\n    for(j = 0; j < n; j++) {\n      if (matrix[i][j] > max) max = matrix[i][j];\n    }\n  }\n  return max;\n}\n```",
  "hint": "Πόσες φορές τρέχει ο εσωτερικός βρόχος για *κάθε* επανάληψη του εξωτερικού; Μετά\nσκεφτείτε αν η αρχική τιμή `max = -1` είναι σωστή για κάθε πίνακα."
 },
 {
  "id": "slides-lec15-complexity-grade",
  "kind": "slides",
  "title": "Πολυπλοκότητα υπολογισμού βαθμολογίας",
  "source": {
   "title": "Διάλεξη 15, διαφάνεια 21",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec15.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   15,
   5
  ],
  "topics": [
   "complexity",
   "functions"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α15.3",
  "path": "questions/slides/slides-lec15-complexity-grade.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec15-complexity-grade.html",
  "statement": "Το γνωστό μας παράδειγμα: Υπολογισμός Βαθμολογίας. Τι χρονική και τι χωρική\nπολυπλοκότητα έχει η συνάρτηση;\n\n```c\n// Compute grades using the class formula\nint grade(int final_exam, int homework, int lab, int year) {\n  if (year <= 1) {\n    return final_exam * 50 / 100 + homework * 30 / 100 + lab * 20 / 100;\n  } else {\n    return final_exam * 70 / 100 + homework * 30 / 100;\n  }\n}\n```",
  "hint": "Υπάρχει κάποια ποσότητα της εισόδου που κάνει τη συνάρτηση να εκτελεί περισσότερα\nβήματα; Αν ο αριθμός των πράξεων δεν εξαρτάται από την είσοδο, ποια κλάση είναι;"
 },
 {
  "id": "slides-lec15-complexity-malloc",
  "kind": "slides",
  "title": "Πολυπλοκότητα δυναμικού πίνακα με malloc",
  "source": {
   "title": "Διάλεξη 15, διαφάνεια 19",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec15.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   15,
   12
  ],
  "topics": [
   "complexity",
   "dynamic-memory",
   "arrays"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α15.4",
  "path": "questions/slides/slides-lec15-complexity-malloc.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec15-complexity-malloc.html",
  "statement": "Με την βοήθεια των δεικτών, μπορούμε να χρησιμοποιήσουμε δυναμικούς πίνακες, πίνακες\nτων οποίων το μέγεθος καθορίζεται δυναμικά, δηλαδή την στιγμή που τρέχει το\nπρόγραμμα. Παράδειγμα:\n\n```c\nint * array = malloc(N * sizeof(int));\nfor(int i = 0 ; i < N ; i++)\n  array[i] = i * i;\n```\n\nΤι χρονική και τι χωρική πολυπλοκότητα έχει ο κώδικας ως προς το `N`;",
  "hint": "Ο χρόνος και ο χώρος δεν έχουν πάντα την ίδια πολυπλοκότητα. Εδώ αναρωτηθείτε πόση\nμνήμη ζητά η `malloc` συναρτήσει του `N`."
 },
 {
  "id": "slides-lec15-complexity-mirror",
  "kind": "slides",
  "title": "Πολυπλοκότητα εύρεσης κατόπτρου ακεραίου",
  "source": {
   "title": "Διάλεξη 15, διαφάνεια 37",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec15.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   15
  ],
  "topics": [
   "complexity",
   "loops",
   "math-algorithms"
  ],
  "difficulty": 2,
  "type": "short-answer",
  "label": "Α15.12",
  "path": "questions/slides/slides-lec15-complexity-mirror.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec15-complexity-mirror.html",
  "statement": "Εύρεση του κατόπτρου ενός ακεραίου. Τι χρονική και τι χωρική πολυπλοκότητα έχει η\nσυνάρτηση ως προς την τιμή του `n`;\n\n```c\nint mirror(int n) {\n  int result = 0, tmp;\n  while(n > 0) {\n    tmp = n % 10;\n    result = 10 * result + tmp;\n    n /= 10;\n  }\n  return result;\n}\n```",
  "hint": "Τι παθαίνει το `n` σε κάθε επανάληψη; Πόσες επαναλήψεις γίνονται για `n = 9`, `99`,\n`999`; Ποια συνάρτηση του `n` μετρά αυτό το πλήθος;"
 },
 {
  "id": "slides-lec15-complexity-odd-multiples-of-7",
  "kind": "slides",
  "title": "Πολυπλοκότητα: γινόμενο περιττών πολλαπλασίων του 7",
  "source": {
   "title": "Διάλεξη 15, διαφάνεια 13",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec15.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   15,
   7
  ],
  "topics": [
   "complexity",
   "loops"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α15.5",
  "path": "questions/slides/slides-lec15-complexity-odd-multiples-of-7.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec15-complexity-odd-multiples-of-7.html",
  "statement": "Θέλω να βρω το γινόμενο όλων των περιττών από το 1 μέχρι το N που διαιρούνται με το\n7. Πώς;\n\nΈνα for loop με μια μεταβλητή που αυξάνεται και έλεγχο για mod 7 = 0:\n\n```c\nfor(product = 1, i = 1; i < N ; i += 2) {\n  if ( i % 7 == 0 )\n    product *= i;\n}\n```\n\nΤι χρονική και τι χωρική πολυπλοκότητα έχει ο βρόχος ως προς το `N`;",
  "hint": "Μετρήστε πόσες φορές εκτελείται το σώμα του βρόχου συναρτήσει του `N`, και θυμηθείτε\nτι κάνει ο συμβολισμός $O$ στους σταθερούς παράγοντες. Για τον χώρο, ρωτήστε αν\nκάποια δομή μεγαλώνει με το `N`. Ελέγξτε επίσης αν ο βρόχος εξετάζει το ίδιο το `N`."
 },
 {
  "id": "slides-lec15-complexity-perfect-squares",
  "kind": "slides",
  "title": "Άθροισμα τέλειων τετραγώνων: δύο εκδοχές",
  "source": {
   "title": "Διάλεξη 15, διαφάνεια 33",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec15.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   15
  ],
  "topics": [
   "complexity",
   "loops",
   "math-algorithms",
   "command-line-args"
  ],
  "difficulty": 2,
  "type": "short-answer",
  "label": "Α15.13",
  "path": "questions/slides/slides-lec15-complexity-perfect-squares.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec15-complexity-perfect-squares.html",
  "statement": "Άθροισμα τέλειων τετραγώνων. Τι χρονική και τι χωρική πολυπλοκότητα έχει η πρώτη\nεκδοχή;\n\n```c\nint isPerfectSquare(int num) {\n  int root = sqrt(num);\n  return root * root == num;\n}\nint low = atoi(argv[1]);\nint high = atoi(argv[2]);\nint i, sum = 0;\nfor(i = low ; i <= high ; i++) {\n  if (isPerfectSquare(i))\n    sum += i;\n}\n```\n\nΚαι η δεύτερη;\n\n```c\nint low = atoi(argv[1]);\nint high = atoi(argv[2]);\nint i, sum = 0;\nfor(i = sqrt(low) ; i <= sqrt(high) ; i++)\n  sum += i*i ;\n```",
  "hint": "Και στις δύο, μετρήστε τις επαναλήψεις συναρτήσει του μεγέθους του διαστήματος\n(θεωρήστε την `sqrt` ένα βήμα). Η δεύτερη διατρέχει άλλες τιμές από την πρώτη: ποιες;\nΔοκιμάστε επίσης τη δεύτερη με `low = 5`, `high = 20` και συγκρίνετε με την πρώτη."
 },
 {
  "id": "slides-lec15-complexity-strcmp",
  "kind": "slides",
  "title": "Πολυπλοκότητα της strcmp",
  "source": {
   "title": "Διάλεξη 15, διαφάνεια 31",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec15.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   15,
   14
  ],
  "topics": [
   "complexity",
   "strings",
   "pointers"
  ],
  "difficulty": 2,
  "type": "short-answer",
  "label": "Α15.14",
  "path": "questions/slides/slides-lec15-complexity-strcmp.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec15-complexity-strcmp.html",
  "statement": "Η συνάρτηση strcmp. Μια πιθανή υλοποίηση:\n\n```c\nint strcmp(char * str1, char * str2) {\n  while(*str1 && (*str1 == *str2)) {\n    str1++;\n    str2++;\n  }\n  return *str1 - *str2;\n}\n```\n\nΤι πολυπλοκότητας είναι η συνάρτηση strcmp ως προς το μέγεθος των συμβολοσειρών\n(έστω n και m);",
  "hint": "Βρείτε όλους τους λόγους για τους οποίους σταματά ο βρόχος. Ποια είναι η χειρότερη\nπερίπτωση, και ποιο από τα δύο μήκη την περιορίζει;"
 },
 {
  "id": "slides-lec15-complexity-strlen",
  "kind": "slides",
  "title": "Πολυπλοκότητα της strlen",
  "source": {
   "title": "Διάλεξη 15, διαφάνεια 29",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec15.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   15,
   14
  ],
  "topics": [
   "complexity",
   "strings",
   "pointers"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α15.6",
  "path": "questions/slides/slides-lec15-complexity-strlen.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec15-complexity-strlen.html",
  "statement": "Η συνάρτηση strlen. Μια πιθανή υλοποίηση:\n\n```c\nsize_t strlen(char * str) {\n  size_t length = 0;\n  while(*str++) length++;\n  return length;\n}\n```\n\nΤι πολυπλοκότητας είναι η συνάρτηση strlen ως προς το μέγεθος της συμβολοσειράς;",
  "hint": "Πότε σταματά ο βρόχος και πόσους χαρακτήρες έχει περάσει μέχρι τότε; Υπάρχει τρόπος\nνα βρεθεί το μήκος χωρίς να διατρέξουμε τη συμβολοσειρά;"
 },
 {
  "id": "slides-lec15-getchar-count",
  "kind": "slides",
  "title": "Τι κάνει το πρόγραμμα με την getchar",
  "source": {
   "title": "Διάλεξη 15, διαφάνεια 17",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec15.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   15,
   9
  ],
  "topics": [
   "complexity",
   "input-output",
   "loops"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α15.7",
  "path": "questions/slides/slides-lec15-getchar-count.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec15-getchar-count.html",
  "statement": "Διαδοχικές κλήσεις της `getchar()` διαβάζουν διαδοχικούς χαρακτήρες. Τι κάνει το\nπαρακάτω πρόγραμμα; Τι χρονική και τι χωρική πολυπλοκότητα έχει;\n\n```c\n#include <stdio.h>\n\nint main() {\n  int ch, sum = 0;\n  printf(\"Enter characters: \");\n  while( (ch = getchar()) != '\\n' && ch != EOF ) {\n    printf(\"%c\", ch);\n    sum++;\n  }\n  printf(\"\\nTotal characters: %d\\n\", sum);\n  return 0;\n}\n```",
  "hint": "Ακολουθήστε τον βρόχο για την είσοδο `hello` και Enter: πότε σταματά και τι τυπώνεται\nσε κάθε επανάληψη; Για τον χώρο, ρωτήστε αν το πρόγραμμα κρατά κάπου όλη τη γραμμή."
 },
 {
  "id": "slides-lec15-macro-prod",
  "kind": "slides",
  "title": "Τι επιστρέφει το πρόγραμμα με τη μακροεντολή PROD",
  "source": {
   "title": "Διάλεξη 15, διαφάνεια 47",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec15.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   15
  ],
  "topics": [
   "preprocessor",
   "precedence"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α15.8",
  "path": "questions/slides/slides-lec15-macro-prod.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec15-macro-prod.html",
  "statement": "Η μακροεντολή αντικαθίσταται στον κώδικα πριν την μεταγλώττιση. Τι θα επιστρέψει το\nπαρακάτω πρόγραμμα;\n\n```c\n#define PROD 2*5\nint main() {\n  return 20 / PROD;\n}\n```",
  "hint": "Γράψτε τη γραμμή `return` όπως θα τη δει ο μεταγλωττιστής μετά την αντικατάσταση\n(ή τρέξτε `cpp` στο αρχείο), και υπολογίστε την παράσταση με τους κανόνες\nπροτεραιότητας και προσεταιριστικότητας. Την τιμή επιστροφής τη βλέπετε με `echo $?`."
 },
 {
  "id": "slides-lec15-preprocess-if-else",
  "kind": "slides",
  "title": "Σε τι προεπεξεργάζεται το #if 0",
  "source": {
   "title": "Διάλεξη 15, διαφάνεια 50",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec15.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   15
  ],
  "topics": [
   "preprocessor"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α15.9",
  "path": "questions/slides/slides-lec15-preprocess-if-else.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec15-preprocess-if-else.html",
  "statement": "Οι εντολές `#if #else #endif` έχουν μορφή παρόμοια με την δομή ελέγχου if στην C αλλά\nδρουν στο επίπεδο του κώδικα. Σε τι θα προεπεξεργαστεί το ακόλουθο πρόγραμμα;\n\n```c\nint main() {\n#if 0\n  return 42;\n#else\n  return 1;\n#endif\n}\n```",
  "hint": "Η συνθήκη του `#if` είναι σταθερά: είναι αληθής ή ψευδής; Κρατήστε μόνο τις γραμμές\nτου κλάδου που επιλέγεται και σβήστε όλες τις γραμμές που αρχίζουν με `#`. Επιβεβαιώστε\nμε `gcc -E`."
 },
 {
  "id": "slides-lec15-prime-complexity",
  "kind": "slides",
  "title": "Πολυπλοκότητα ελέγχου αν ένας αριθμός είναι πρώτος",
  "source": {
   "title": "Διάλεξη 15, διαφάνεια 39",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec15.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   15
  ],
  "topics": [
   "complexity",
   "math-algorithms",
   "loops"
  ],
  "difficulty": 2,
  "type": "short-answer",
  "label": "Α15.15",
  "path": "questions/slides/slides-lec15-prime-complexity.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec15-prime-complexity.html",
  "statement": "Έλεγχος αν ένας αριθμός είναι πρώτος - τι χρονική πολυπλοκότητα έχει;",
  "hint": "Γράψτε πρώτα τον απλό αλγόριθμο που δοκιμάζει διαιρέτες και μετρήστε τις δοκιμές για\nαριθμό $n$. Μετά σκεφτείτε: αν ο $n$ έχει διαιρέτη μεγαλύτερο από $\\sqrt{n}$, τι\nισχύει για τον «συμπληρωματικό» του διαιρέτη; Πώς αλλάζει αυτό το όριο του βρόχου;"
 },
 {
  "id": "slides-lec16-atoi",
  "kind": "slides",
  "title": "Η atoi και τι μπορεί να πάει στραβά",
  "source": {
   "title": "Διάλεξη 16, διαφάνειες 16–17",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec16.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   16,
   11
  ],
  "topics": [
   "strings",
   "input-validation",
   "functions"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α16.9",
  "path": "questions/slides/slides-lec16-atoi.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec16-atoi.html",
  "statement": "Θέλω μια συνάρτηση `atoi` που να παίρνει ένα πίνακα χαρακτήρων (μόνο ψηφία) και να\nεπιστρέφει έναν ακέραιο. Πώς;\n\nΗ λύση των διαφανειών είναι η εξής. Τι μπορεί να πάει στραβά με αυτήν τη συνάρτηση;\n\n```c\nint atoi(char digits[]) {\n  int result = 0;\n  for(int i = 0; digits[i]; i++) {\n    result = 10 * result + digits[i] - '0';\n  }\n  return result;\n}\n```",
  "hint": "Γράψτε τις υποθέσεις που κάνει η συνάρτηση για την είσοδό της και δοκιμάστε νοερά\nεισόδους που τις παραβιάζουν: πρόσημο ή γράμματα, έναν πολύ μεγάλο αριθμό, έναν\nπίνακα χωρίς `'\\0'`. Σκεφτείτε και το όνομά της."
 },
 {
  "id": "slides-lec16-average-complexity",
  "kind": "slides",
  "title": "Μέσος όρος πίνακα και πολυπλοκότητα",
  "source": {
   "title": "Διάλεξη 16, διαφάνειες 8–9",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec16.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   16,
   10
  ],
  "topics": [
   "arrays",
   "functions",
   "complexity"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α16.1",
  "path": "questions/slides/slides-lec16-average-complexity.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec16-average-complexity.html",
  "statement": "Θέλω μια συνάρτηση που να δέχεται έναν πίνακα 100 ακεραίων και να επιστρέφει τον\nμέσο όρο. Πώς; Χρονική και χωρική πολυπλοκότητα;",
  "hint": "Ένας συσσωρευτής και ένα πέρασμα από τον πίνακα αρκούν. Για την πολυπλοκότητα,\nμετρήστε πόσες φορές εκτελείται το σώμα του βρόχου αν ο πίνακας είχε $n$ στοιχεία, και\nπόσες βοηθητικές μεταβλητές χρειάζεστε. Προσέξτε αν η διαίρεση στο τέλος είναι ακέραια."
 },
 {
  "id": "slides-lec16-char-pointer-arrays",
  "kind": "slides",
  "title": "char *array[], char **array και char array[10][10]",
  "source": {
   "title": "Διάλεξη 16, διαφάνεια 19",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec16.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   16,
   12
  ],
  "topics": [
   "pointers",
   "arrays",
   "multidim-arrays"
  ],
  "difficulty": 2,
  "type": "short-answer",
  "label": "Α16.10",
  "path": "questions/slides/slides-lec16-char-pointer-arrays.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec16-char-pointer-arrays.html",
  "statement": "Ποια η διαφορά ενός `char * array[]` και ενός `char ** array`; Έχει διαφορά από έναν\n`char array[10][10]`;",
  "hint": "Σχεδιάστε τη μνήμη για καθεμία: πόσα bytes πιάνει (τι δίνει το `sizeof`), πού υπάρχουν\nαποθηκευμένοι pointers και πού σκέτοι χαρακτήρες. Μετά σκεφτείτε σε ποιον τύπο\nμετατρέπεται το καθένα όταν περνά ως όρισμα σε συνάρτηση."
 },
 {
  "id": "slides-lec16-fibonacci-efficient",
  "kind": "slides",
  "title": "Αποδοτική αναδρομική Fibonacci",
  "source": {
   "title": "Διάλεξη 16, διαφάνεια 26",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec16.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   16,
   11
  ],
  "topics": [
   "recursion",
   "complexity",
   "dynamic-programming"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α16.11",
  "path": "questions/slides/slides-lec16-fibonacci-efficient.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec16-fibonacci-efficient.html",
  "statement": "Θέλω μια αναδρομική υλοποίηση που να υπολογίζει τους fibonacci αριθμούς αποδοτικά.\nΓίνεται;",
  "hint": "Σχεδιάστε το δέντρο κλήσεων της απλής αναδρομής για ένα μικρό `n` και μετρήστε πόσες\nφορές υπολογίζεται η ίδια τιμή. Τι θα γινόταν αν θυμόσασταν τα αποτελέσματα που έχετε\nήδη βρει; Εναλλακτικά, τι θα έπρεπε να «κουβαλά» κάθε κλήση ώστε να αρκεί μία\nαναδρομική κλήση;"
 },
 {
  "id": "slides-lec16-find-complexity",
  "kind": "slides",
  "title": "Αναζήτηση σε πίνακα και πολυπλοκότητα",
  "source": {
   "title": "Διάλεξη 16, διαφάνειες 10 και 15",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec16.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   16,
   10
  ],
  "topics": [
   "arrays",
   "searching",
   "complexity"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α16.2",
  "path": "questions/slides/slides-lec16-find-complexity.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec16-find-complexity.html",
  "statement": "Θέλω μια συνάρτηση που να δέχεται έναν πίνακα 100 ακεραίων και έναν ακέραιο και να\nγυρνάει τη θέση του στοιχείου αν το βρήκε ή -1. Πώς; Χρονική και χωρική\nπολυπλοκότητα;",
  "hint": "Ελέγξτε τα στοιχεία ένα-ένα και επιστρέψτε μόλις βρείτε αυτό που ψάχνετε. Για την\nπολυπλοκότητα, σκεφτείτε ποια είσοδος κάνει τη συνάρτηση να δουλέψει περισσότερο."
 },
 {
  "id": "slides-lec16-find-duplicate",
  "kind": "slides",
  "title": "Το στοιχείο που υπάρχει δύο φορές",
  "source": {
   "title": "Διάλεξη 16, διαφάνεια 11",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec16.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   16
  ],
  "topics": [
   "arrays",
   "complexity",
   "problem-solving"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α16.12",
  "path": "questions/slides/slides-lec16-find-duplicate.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec16-find-duplicate.html",
  "statement": "Θέλουμε μια συνάρτηση που παίρνει ως όρισμα έναν πίνακα ακεραίων και βρίσκει το\nστοιχείο που υπάρχει δύο φορές - όλα τα υπόλοιπα στοιχεία θα υπάρχουν ακριβώς μία\nφορά. Για παράδειγμα, αν δοθεί ο πίνακας {8, 1, 5, 42, 7, 3, 42} θα πρέπει να\nεπιστρέψει την τιμή 42.",
  "hint": "Η απλή λύση συγκρίνει κάθε ζεύγος στοιχείων· προσέξτε να μη συγκρίνετε ένα στοιχείο με\nτον εαυτό του. Μετά σκεφτείτε πώς θα γινόταν ταχύτερα: τι αλλάζει αν ο πίνακας είναι\nταξινομημένος, ή αν οι τιμές έχουν μικρό εύρος και μπορείτε να ξοδέψετε μνήμη;"
 },
 {
  "id": "slides-lec16-get-two-chars",
  "kind": "slides",
  "title": "Η συνάρτηση get_two_chars",
  "source": {
   "title": "Διάλεξη 16, διαφάνεια 20",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec16.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   16,
   11
  ],
  "topics": [
   "functions",
   "pointers",
   "input-output"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α16.3",
  "path": "questions/slides/slides-lec16-get-two-chars.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec16-get-two-chars.html",
  "statement": "Θέλω να γράψω μια συνάρτηση `get_two_chars` που να διαβάζει *δύο* χαρακτήρες και να\nτους επιστρέφει. Πώς;",
  "hint": "Το `return` επιστρέφει μόνο μία τιμή. Πώς μπορεί μια συνάρτηση να γράψει σε μεταβλητές\nτου καλούντος; Σκεφτείτε τι θα επιστρέφει το ίδιο το `return` και τι γίνεται όταν η\nείσοδος τελειώσει."
 },
 {
  "id": "slides-lec16-heap-2d-array",
  "kind": "slides",
  "title": "Δισδιάστατος πίνακας στον σωρό",
  "source": {
   "title": "Διάλεξη 16, διαφάνεια 25",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec16.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   16,
   13
  ],
  "topics": [
   "dynamic-memory",
   "multidim-arrays",
   "pointers"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α16.13",
  "path": "questions/slides/slides-lec16-heap-2d-array.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec16-heap-2d-array.html",
  "statement": "Θέλω να δημιουργήσω έναν δισδιάστατο πίνακα στον σωρό. Πώς μπορώ να το κάνω αυτό;",
  "hint": "Δύο δρόμοι: ένας πίνακας από pointers γραμμών, όπου κάθε γραμμή έχει τη δική της\n`malloc`, ή ένα ενιαίο μπλοκ για όλα τα στοιχεία, όπου υπολογίζετε μόνοι σας τη θέση\nτου στοιχείου `[i][j]`. Μην ξεχάσετε τον έλεγχο για `NULL` και τη σωστή σειρά των\n`free`."
 },
 {
  "id": "slides-lec16-palindrome-number",
  "kind": "slides",
  "title": "Παλινδρομικός αριθμός",
  "source": {
   "title": "Διάλεξη 16, διαφάνεια 21",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec16.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   16,
   8
  ],
  "topics": [
   "math-algorithms",
   "loops",
   "functions"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α16.4",
  "path": "questions/slides/slides-lec16-palindrome-number.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec16-palindrome-number.html",
  "statement": "Θέλω να βρω αν ένας αριθμός είναι παλινδρομικός. Πώς μπορώ να το βρω;",
  "hint": "Ένας αριθμός είναι παλινδρομικός αν διαβάζεται ίδια ανάποδα. Έχετε ήδη τρόπο να\nαντιστρέψετε τα ψηφία ενός αριθμού· εναλλακτικά, βάλτε τα ψηφία σε πίνακα και\nσυγκρίνετέ τα από τα δύο άκρα. Αποφασίστε τι ισχύει για αρνητικούς."
 },
 {
  "id": "slides-lec16-reverse-digits",
  "kind": "slides",
  "title": "Αντιστροφή ψηφίων αριθμού",
  "source": {
   "title": "Διάλεξη 16, διαφάνεια 13",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec16.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   16,
   8
  ],
  "topics": [
   "math-algorithms",
   "loops",
   "functions"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α16.5",
  "path": "questions/slides/slides-lec16-reverse-digits.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec16-reverse-digits.html",
  "statement": "Θέλω μια συνάρτηση που να αντιστρέφει τα ψηφία ενός αριθμού, για παράδειγμα αν δοθεί\nτο 123, θέλω να επιστρέφει το 321. Πώς;",
  "hint": "Ποια πράξη σας δίνει το τελευταίο ψηφίο ενός αριθμού και ποια τον αριθμό χωρίς αυτό;\nΧτίστε το αποτέλεσμα ψηφίο-ψηφίο, «σπρώχνοντας» ό,τι έχετε ήδη μία θέση αριστερά.\nΣκεφτείτε τι γίνεται με το 1200 και με πολύ μεγάλους αριθμούς."
 },
 {
  "id": "slides-lec16-search-2d",
  "kind": "slides",
  "title": "yes αν ένα στοιχείο υπάρχει σε δισδιάστατο πίνακα",
  "source": {
   "title": "Διάλεξη 16, διαφάνεια 24",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec16.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   16,
   12
  ],
  "topics": [
   "multidim-arrays",
   "loops",
   "control-flow"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α16.6",
  "path": "questions/slides/slides-lec16-search-2d.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec16-search-2d.html",
  "statement": "Θέλω να τυπώσω \"yes\" αν ένα στοιχείο βρίσκεται σε έναν δισδιάστατο πίνακα. Πώς;",
  "hint": "Δύο εμφωλευμένοι βρόχοι διατρέχουν τον πίνακα. Η δυσκολία είναι να σταματήσετε μόλις\nτο βρείτε: από πόσους βρόχους βγάζει ένα `break`; Σκεφτείτε μια βοηθητική συνάρτηση ή\nμια μεταβλητή-σημαία, ώστε το \"yes\" να τυπωθεί ακριβώς μία φορά."
 },
 {
  "id": "slides-lec16-single-unpaired",
  "kind": "slides",
  "title": "Το στοιχείο χωρίς ζευγάρι",
  "source": {
   "title": "Διάλεξη 16, διαφάνεια 14",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec16.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   16,
   4
  ],
  "topics": [
   "arrays",
   "bitwise",
   "complexity"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α16.14",
  "path": "questions/slides/slides-lec16-single-unpaired.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec16-single-unpaired.html",
  "statement": "Έχω έναν πίνακα ακεραίων και όλα τα στοιχεία του είναι διπλά εκτός από ένα. Πώς το\nβρίσκω αποδοτικά;",
  "hint": "Υπάρχει τελεστής bit για τον οποίο ένας αριθμός «ακυρώνει» τον εαυτό του και το 0\nείναι ουδέτερο στοιχείο. Στοχεύστε σε ένα πέρασμα από τον πίνακα, χωρίς βοηθητικό\nπίνακα και χωρίς ταξινόμηση."
 },
 {
  "id": "slides-lec16-sum-perfect-squares",
  "kind": "slides",
  "title": "Άθροισμα τέλειων τετραγώνων σε διάστημα",
  "source": {
   "title": "Διάλεξη 16, διαφάνεια 18",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec16.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   16
  ],
  "topics": [
   "math-algorithms",
   "complexity",
   "loops"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α16.15",
  "path": "questions/slides/slides-lec16-sum-perfect-squares.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec16-sum-perfect-squares.html",
  "statement": "Θέλω να βρω το άθροισμα των τέλειων τετραγώνων μέσα σε ένα διάστημα αριθμών. Πώς το\nβρίσκω αποδοτικά;",
  "hint": "Αντί να ελέγχετε κάθε αριθμό του διαστήματος, σκεφτείτε πόσα τέλεια τετράγωνα υπάρχουν\nμέχρι το $b$ και απαριθμήστε απευθείας αυτά. Υπάρχει και κλειστός τύπος για το\n$1^2 + 2^2 + \\dots + m^2$. Προσέξτε την υπερχείλιση."
 },
 {
  "id": "slides-lec16-swap",
  "kind": "slides",
  "title": "Η συνάρτηση swap",
  "source": {
   "title": "Διάλεξη 16, διαφάνειες 22–23",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec16.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   16,
   11
  ],
  "topics": [
   "pointers",
   "functions"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α16.7",
  "path": "questions/slides/slides-lec16-swap.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec16-swap.html",
  "statement": "Γράψτε μια συνάρτηση `swap` που ανταλλάζει δύο ακεραίους.\n\n```c\n#include <stdio.h>\nint main() {\n  int a = 100, b = 200;\n  printf(\"%d %d\\n\", a, b);\n  swap( ... );\n  printf(\"%d %d\\n\", a, b);\n  return 0;\n}\n```",
  "hint": "Τα ορίσματα περνούν κατά τιμή, οπότε μια `swap(a, b)` θα άλλαζε μόνο αντίγραφα. Τι\nπρέπει να περάσει η `main` ώστε η `swap` να μπορεί να γράψει στις δικές της `a` και\n`b`; Θα χρειαστείτε και μια προσωρινή μεταβλητή."
 },
 {
  "id": "slides-lec16-why-practice",
  "kind": "slides",
  "title": "Γιατί εξάσκηση στην επίλυση προβλημάτων;",
  "source": {
   "title": "Διάλεξη 16, διαφάνειες 5–6",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec16.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   16,
   7
  ],
  "topics": [
   "problem-solving"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α16.8",
  "path": "questions/slides/slides-lec16-why-practice.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec16-why-practice.html",
  "statement": "Γιατί κάνουμε εξάσκηση στην επίλυση προβλημάτων;",
  "hint": "Σκεφτείτε τι κερδίζετε από κάθε πρόβλημα που λύνετε, πέρα από τη συγκεκριμένη λύση:\nτι μένει για το επόμενο πρόβλημα, πού θα ξανασυναντήσετε τα ίδια μοτίβα, και τι\nσημαίνει να συνδυάζετε γνωστές ιδέες σε κάτι νέο."
 },
 {
  "id": "slides-lec17-binary-search-bug",
  "kind": "slides",
  "title": "Το σφάλμα της δυαδικής αναζήτησης",
  "source": {
   "title": "Διάλεξη 17: Δυαδική Αναζήτηση και Ταξινόμηση, διαφάνεια 16",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec17.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   17
  ],
  "topics": [
   "searching",
   "integer-representation",
   "undefined-behavior"
  ],
  "difficulty": 2,
  "type": "debug",
  "label": "Α17.8",
  "path": "questions/slides/slides-lec17-binary-search-bug.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec17-binary-search-bug.html",
  "statement": "Αυτός ο αλγόριθμος έχει σφάλμα, μπορούμε να το βρούμε και να το διορθώσουμε;\n\n```c\nint binary_search(int elem, int *array, int n) {\n  int mid, low = 0, high = n - 1;\n  while (low <= high) {\n    mid = (low + high) / 2;\n    if (array[mid] == elem)\n      return 1;\n    else if (array[mid] < elem)\n      low = mid + 1;\n    else\n      high = mid - 1;\n  }\n  return 0;\n}\n```",
  "hint": "Η λογική του αλγορίθμου είναι σωστή για μικρούς πίνακες. Σκεφτείτε έναν πίνακα με δύο δισεκατομμύρια στοιχεία: ποιες τιμές μπορούν να πάρουν τα `low` και `high`, και χωράει πάντα το άθροισμά τους σε `int`; Βρείτε μια έκφραση για το μέσο που δεν αθροίζει δύο μεγάλες θέσεις."
 },
 {
  "id": "slides-lec17-binary-search-complexity",
  "kind": "slides",
  "title": "Πολυπλοκότητα της δυαδικής αναζήτησης",
  "source": {
   "title": "Διάλεξη 17: Δυαδική Αναζήτηση και Ταξινόμηση, διαφάνεια 18",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec17.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   17
  ],
  "topics": [
   "searching",
   "complexity"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α17.1",
  "path": "questions/slides/slides-lec17-binary-search-complexity.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec17-binary-search-complexity.html",
  "statement": "Τι πολυπλοκότητα (χρόνου και χώρου) έχει αυτός ο αλγόριθμος;\n\n```c\nint binary_search(int elem, int *array, int n) {\n  int mid, low = 0, high = n - 1;\n  while (low <= high) {\n    mid = low + (high - low) / 2;\n    if (array[mid] == elem)\n      return 1;\n    else if (array[mid] < elem)\n      low = mid + 1;\n    else\n      high = mid - 1;\n  }\n  return 0;\n}\n```",
  "hint": "Πόσα στοιχεία μένουν στο διάστημα `[low, high]` μετά από κάθε γύρο του βρόχου; Μετρήστε πόσες φορές μπορείτε να διαιρέσετε το $n$ με το 2 μέχρι να φτάσετε στο 1. Για τον χώρο, μετρήστε τις μεταβλητές που χρησιμοποιεί η συνάρτηση."
 },
 {
  "id": "slides-lec17-binary-search",
  "kind": "slides",
  "title": "Δυαδική αναζήτηση σε ταξινομημένο πίνακα",
  "source": {
   "title": "Διάλεξη 17: Δυαδική Αναζήτηση και Ταξινόμηση, διαφάνεια 14",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec17.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   17
  ],
  "topics": [
   "searching",
   "arrays",
   "pointers"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α17.7",
  "path": "questions/slides/slides-lec17-binary-search.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec17-binary-search.html",
  "statement": "Θέλω μια συνάρτηση που να δέχεται έναν πίνακα n ταξινομημένων ακεραίων σε αύξουσα σειρά και έναν ακέραιο που ψάχνουμε και να γυρνάει αν υπάρχει στον πίνακα ή όχι. Πως;\n\n```c\nint binary_search(int elem, int *array, int n);\n```",
  "hint": "Κρατήστε δύο δείκτες θέσης, `low` και `high`, για το τμήμα όπου μπορεί ακόμη να βρίσκεται το στοιχείο, και συγκρίνετε με το μεσαίο στοιχείο του τμήματος. Σκεφτείτε προσεκτικά τη συνθήκη του βρόχου (τι γίνεται όταν μένει ένα στοιχείο;) και ποια είναι τα νέα όρια, ώστε το τμήμα να μικραίνει πάντα."
 },
 {
  "id": "slides-lec17-faster-than-linear",
  "kind": "slides",
  "title": "Γρηγορότερα από O(n);",
  "source": {
   "title": "Διάλεξη 17: Δυαδική Αναζήτηση και Ταξινόμηση, διαφάνεια 11",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec17.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   17
  ],
  "topics": [
   "searching",
   "complexity"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α17.2",
  "path": "questions/slides/slides-lec17-faster-than-linear.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec17-faster-than-linear.html",
  "statement": "Η γραμμική αναζήτηση βρίσκει ένα στοιχείο σε μια ακολουθία $n$ στοιχείων σε χρόνο $O(n)$.\n\nΜπορούμε να βρούμε ένα στοιχείο πιο γρήγορα από $O(n)$;",
  "hint": "Σκεφτείτε πρώτα τι θα μπορούσε να συμβαίνει σε ένα στοιχείο που δεν κοιτάξατε, αν ο πίνακας δεν έχει καμία δομή. Έπειτα σκεφτείτε πώς ψάχνετε μια λέξη σε ένα λεξικό: ποια ιδιότητα των δεδομένων σάς επιτρέπει να μην τα κοιτάξετε όλα;"
 },
 {
  "id": "slides-lec17-guess-100",
  "kind": "slides",
  "title": "Ο γρίφος του κρυμμένου αριθμού",
  "source": {
   "title": "Διάλεξη 17: Δυαδική Αναζήτηση και Ταξινόμηση, διαφάνεια 5",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec17.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   17
  ],
  "topics": [
   "searching",
   "problem-solving"
  ],
  "difficulty": 2,
  "type": "short-answer",
  "label": "Α17.9",
  "path": "questions/slides/slides-lec17-guess-100.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec17-guess-100.html",
  "statement": "Έχω έναν αριθμό στο νου μου στο διάστημα $[1, 100]$. Θέλετε να τον βρείτε. Μπορείτε να με ρωτήσετε ό,τι ερώτηση θέλετε και εγώ απαντάω ναι ή όχι.\n\n- Αν τον βρείτε στην 1η προσπάθεια => κερδίζετε 5€\n- Αν τον βρείτε στην 2η προσπάθεια => κερδίζετε 4€\n- Αν τον βρείτε στην 3η προσπάθεια => κερδίζετε 3€\n- Αν τον βρείτε στην 4η προσπάθεια => κερδίζετε 2€\n- Αν τον βρείτε στην 5η προσπάθεια => κερδίζετε 1€\n- Αν τον βρείτε στην 6η προσπάθεια => κερδίζετε 0€\n- Αν τον βρείτε στην 7η προσπάθεια => μου δίνετε 1€\n\nΠαίζουμε;\n\n(Microsoft Interview Question by Steve Ballmer.)",
  "hint": "Βρείτε πρώτα πόσες ερωτήσεις χρειάζεται στη χειρότερη περίπτωση η στρατηγική που μοιράζει κάθε φορά το διάστημα στη μέση, και πόσους αριθμούς μπορείτε να εντοπίσετε με 1, 2, 3, … ερωτήσεις. Έπειτα σκεφτείτε ότι τον αριθμό τον διαλέγει κάποιος που ξέρει τη στρατηγική σας."
 },
 {
  "id": "slides-lec17-guess-billion",
  "kind": "slides",
  "title": "Κρυμμένος αριθμός έως 10^9",
  "source": {
   "title": "Διάλεξη 17: Δυαδική Αναζήτηση και Ταξινόμηση, διαφάνεια 6",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec17.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   17
  ],
  "topics": [
   "searching",
   "complexity"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α17.3",
  "path": "questions/slides/slides-lec17-guess-billion.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec17-guess-billion.html",
  "statement": "Έχω έναν αριθμό στο νου μου στο διάστημα $[1, 10^9]$.\n\nΘέλετε να τον βρείτε. Μπορείτε να με ρωτήσετε ό,τι ερώτηση θέλετε και εγώ απαντάω ναι ή όχι.\n\nΤι θα με ρωτήσετε; Πόσες προσπάθειες χρειάζεστε για να βρείτε τον αριθμό μου;",
  "hint": "Διαλέξτε ερωτήσεις που χωρίζουν τους υποψήφιους αριθμούς σε δύο ίσα μέρη. Μετά από $k$ τέτοιες ερωτήσεις πόσοι υποψήφιοι μένουν; Βρείτε το μικρότερο $k$ για το οποίο το $2^k$ ξεπερνά το $10^9$."
 },
 {
  "id": "slides-lec17-instagram",
  "kind": "slides",
  "title": "Αναζήτηση χρήστη στο Instagram",
  "source": {
   "title": "Διάλεξη 17: Δυαδική Αναζήτηση και Ταξινόμηση, διαφάνεια 19",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec17.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   17,
   18
  ],
  "topics": [
   "searching",
   "complexity"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α17.4",
  "path": "questions/slides/slides-lec17-instagram.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec17-instagram.html",
  "statement": "Το Instagram έχει 2 δισεκατομμύρια χρήστες σε έναν πίνακα ακεραίων (έστω ένας ακέραιος ανά χρήστη). Πόσα βήματα (χρονική πολυπλοκότητα) χρειάζεστε για να βρείτε αν ο χρήστης 424242 βρίσκεται στον πίνακα;",
  "hint": "Η απάντηση εξαρτάται από το αν ο πίνακας είναι ταξινομημένος. Υπολογίστε τα βήματα της γραμμικής αναζήτησης στη χειρότερη περίπτωση και της δυαδικής, βρίσκοντας τη μικρότερη δύναμη του 2 που ξεπερνά το $2 \\cdot 10^9$."
 },
 {
  "id": "slides-lec17-linear-search",
  "kind": "slides",
  "title": "Αναζήτηση σε πίνακα 100 ακεραίων",
  "source": {
   "title": "Διάλεξη 17: Δυαδική Αναζήτηση και Ταξινόμηση, διαφάνεια 9",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec17.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   17
  ],
  "topics": [
   "searching",
   "arrays",
   "functions"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α17.5",
  "path": "questions/slides/slides-lec17-linear-search.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec17-linear-search.html",
  "statement": "Θέλω μια συνάρτηση που να δέχεται έναν πίνακα 100 ακεραίων και έναν ακέραιο και να γυρνάει την θέση του στοιχείου αν το βρήκε ή -1. Πως;\n\n```c\nint find(int haystack[100], int needle);\n```\n\nΠοια είναι η χρονική πολυπλοκότητα και ο χώρος μνήμης που χρειάζεται;",
  "hint": "Διατρέξτε τον πίνακα με έναν βρόχο και επιστρέψτε μόλις βρείτε ίσο στοιχείο· το `-1` επιστρέφεται μόνο αφού τελειώσει ο βρόχος. Για την πολυπλοκότητα, μετρήστε τις συγκρίσεις στη χειρότερη περίπτωση."
 },
 {
  "id": "slides-lec17-swap",
  "kind": "slides",
  "title": "Η συνάρτηση swap",
  "source": {
   "title": "Διάλεξη 17: Δυαδική Αναζήτηση και Ταξινόμηση, διαφάνεια 21",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec17.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   17,
   18
  ],
  "topics": [
   "pointers",
   "functions"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α17.6",
  "path": "questions/slides/slides-lec17-swap.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec17-swap.html",
  "statement": "Γράψτε μια συνάρτηση `swap` που ανταλλάζει δύο ακεραίους.\n\n```c\n#include <stdio.h>\nint main() {\n  int a = 100, b = 200;\n  printf(\"%d %d\\n\", a, b);\n  swap( ... );\n  printf(\"%d %d\\n\", a, b);\n  return 0;\n}\n```",
  "hint": "Τα ορίσματα στη C περνούν με τιμή, άρα μια συνάρτηση που παίρνει δύο `int` αλλάζει μόνο τα δικά της αντίγραφα. Περάστε στη `swap` τις διευθύνσεις των `a` και `b` και χρησιμοποιήστε μια βοηθητική μεταβλητή."
 },
 {
  "id": "slides-lec18-2d-sizeof",
  "kind": "slides",
  "title": "Μέγεθος δισδιάστατου πίνακα και μιας γραμμής του",
  "source": {
   "title": "Διάλεξη 18, διαφάνεια 2",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec18.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   18,
   12
  ],
  "topics": [
   "multidim-arrays",
   "arrays"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α18.1",
  "path": "questions/slides/slides-lec18-2d-sizeof.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec18-2d-sizeof.html",
  "statement": "Πόσος χώρος δεσμεύεται από τη δήλωση `int array[5][10];`;\n\nΠοιο είναι το `sizeof(array[3])`;",
  "hint": "Ένας δισδιάστατος πίνακας είναι πίνακας από γραμμές: σκεφτείτε πόσα `int` έχει όλος\nο πίνακας και τι τύπου είναι το `array[3]`. Εκφράστε τις απαντήσεις με\n`sizeof(int)`."
 },
 {
  "id": "slides-lec18-fopen-fail",
  "kind": "slides",
  "title": "Γιατί μπορεί να αποτύχει η fopen;",
  "source": {
   "title": "Διάλεξη 18, διαφάνειες 43–44",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec18.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   18
  ],
  "topics": [
   "files"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α18.2",
  "path": "questions/slides/slides-lec18-fopen-fail.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec18-fopen-fail.html",
  "statement": "Ελέγχουμε πάντα το αποτέλεσμα της `fopen` αν είναι `NULL`. Για ποιο λόγο μπορεί να\nαποτύχει;\n\n```c\n#include <stdio.h>\nint main() {\n  FILE *fileToRead, *fileToWrite;\n  fileToRead = fopen(\"input.txt\", \"r\");\n  if (!fileToRead) {\n    return 1;\n  }\n  fileToWrite = fopen(\"output.txt\", \"w\");\n  if (!fileToWrite) {\n    return 1;\n  }\n  return 0;\n}\n```",
  "hint": "Σκεφτείτε ξεχωριστά το άνοιγμα για διάβασμα και για γράψιμο: τι πρέπει να υπάρχει\nήδη, τι πρέπει να επιτρέπεται στον χρήστη και ποιους πόρους του συστήματος\nκαταναλώνει ένα ανοιχτό αρχείο."
 },
 {
  "id": "slides-lec18-fread-int",
  "kind": "slides",
  "title": "Ακέραιοι από αρχείο κειμένου με fread",
  "source": {
   "title": "Διάλεξη 18, διαφάνειες 50–51",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec18.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   18,
   12
  ],
  "topics": [
   "files",
   "integer-representation"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α18.5",
  "path": "questions/slides/slides-lec18-fread-int.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec18-fread-int.html",
  "statement": "Το αρχείο `input.txt` δημιουργήθηκε με `echo hello > input.txt`. Εξηγήστε την\nέξοδο του προγράμματος («What?!»).\n\n```c\n#include <stdio.h>\nint main() {\n  FILE *fileToRead, *fileToWrite;\n  fileToRead = fopen(\"input.txt\", \"r\");\n  if (!fileToRead) return 1;\n  int buffer[1024];\n  size_t integersRead = fread(buffer, sizeof(int), 1023, fileToRead);\n  printf(\"# of integers read: %d\\n\", integersRead);\n  printf(\"Integer read: %d %08x\\n\", buffer[0], buffer[0]);\n  fclose(fileToRead);\n  return 0;\n}\n```\n\n```text\n$ ./freadint\n# of integers read: 1\nInteger read: 1819043176 6c6c6568\n$ hexdump -C input.txt\n00000000  68 65 6c 6c 6f 0a  |hello.|\n```",
  "hint": "Η `fread` αντιγράφει bytes χωρίς καμία μετατροπή και μετρά μόνο ολόκληρα δεδομένα\nμεγέθους `sizeof(int)`. Συγκρίνετε τα bytes του `hexdump` με το δεκαεξαδικό που\nτυπώθηκε και θυμηθείτε το endianness."
 },
 {
  "id": "slides-lec18-hypotenuse",
  "kind": "slides",
  "title": "Υποτείνουσα με scanf",
  "source": {
   "title": "Διάλεξη 18, διαφάνειες 29–30",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec18.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   18,
   9
  ],
  "topics": [
   "input-output",
   "floating-point"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α18.3",
  "path": "questions/slides/slides-lec18-hypotenuse.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec18-hypotenuse.html",
  "statement": "Τι κάνει το παρακάτω πρόγραμμα; Τι τυπώνει αν ο χρήστης δώσει `3.0 4.0`;\n\n```c\n#include <stdio.h>\n#include <math.h>\nint main() {\n  double d1, d2;\n  printf(\"Gimme two doubles: \");\n  scanf(\"%lf %lf\", &d1, &d2);\n  printf(\"Hypotenuse: %.1f\\n\", sqrt(d1 * d1 + d2 * d2));\n  return 0;\n}\n```",
  "hint": "Το `%lf` διαβάζει `double` και το `%.1f` τυπώνει με ένα δεκαδικό. Αναγνωρίστε\nτον τύπο που υπολογίζεται μέσα στη `sqrt` (Πυθαγόρειο θεώρημα)."
 },
 {
  "id": "slides-lec18-scanf-string",
  "kind": "slides",
  "title": "Μια λέξη σε char[7] με scanf",
  "source": {
   "title": "Διάλεξη 18, διαφάνειες 31–35",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec18.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   18,
   12
  ],
  "topics": [
   "strings",
   "input-output",
   "undefined-behavior"
  ],
  "difficulty": 2,
  "type": "debug",
  "label": "Α18.6",
  "path": "questions/slides/slides-lec18-scanf-string.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec18-scanf-string.html",
  "statement": "Τι κάνει το παρακάτω πρόγραμμα;\n\n```c\n#include <stdio.h>\nint main() {\n  char message[7];\n  printf(\"Say something: \");\n  scanf(\"%s\", message);\n  printf(\"%s\\n\", message);\n  return 0;\n}\n```\n\n```text\n$ ./message\nSay something: hello!\nhello!\n```\n\n1. Δεν βάλαμε `&` πριν τη μεταβλητή `message`. Πώς και λειτουργεί;\n2. Μπορεί να πάει κάτι στραβά εδώ; Τι θα συμβεί αν ο χρήστης γράψει\n   `Houston, we've had a problem here.`; Πώς το διορθώνουμε;",
  "hint": "Θυμηθείτε σε τι μετατρέπεται το όνομα ενός πίνακα όταν το περνάμε σε συνάρτηση. Για\nτο δεύτερο σκέλος, μετρήστε πόσους χαρακτήρες (μαζί με το `'\\0'`) διαβάζει το `%s`\nαπό την πρώτη λέξη και πόσοι χωρούν στον πίνακα· η `scanf` δέχεται και πλάτος πεδίου."
 },
 {
  "id": "slides-lec18-stderr-redirect",
  "kind": "slides",
  "title": "Ανακατεύθυνση της stderr",
  "source": {
   "title": "Διάλεξη 18, διαφάνεια 56",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec18.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   18,
   1
  ],
  "topics": [
   "redirection",
   "files"
  ],
  "difficulty": 1,
  "type": "tooling",
  "label": "Α18.4",
  "path": "questions/slides/slides-lec18-stderr-redirect.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec18-stderr-redirect.html",
  "statement": "Σύγκρινε το `find / -name foo` με το `find / -name foo 2> error.txt`.",
  "hint": "Τρέξτε και τις δύο εντολές και δείτε τι εμφανίζεται στην οθόνη και τι στο\n`error.txt`. Ποιον file descriptor έχει η `stderr`, και σε ποιο ρεύμα γράφει η\n`find` τα μηνύματα «Permission denied»;"
 },
 {
  "id": "slides-lec19-date-pointers",
  "kind": "slides",
  "title": "Δείκτες σε δομές: διαφορά ημερομηνιών",
  "source": {
   "title": "Διάλεξη 19, διαφάνειες 42–43",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec19.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   19
  ],
  "topics": [
   "structs",
   "pointers",
   "dynamic-memory"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α19.5",
  "path": "questions/slides/slides-lec19-date-pointers.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec19-date-pointers.html",
  "statement": "Οι δείκτες μπορούν να συνδυαστούν με δομές όπως όλοι οι άλλοι τύποι. Τι θα τυπώσει το\nπαρακάτω πρόγραμμα;\n\n```c\n#include <stdio.h>\n#include <stdlib.h>\ntypedef struct { int day; int month; int year; } Date;\nint main() {\n  Date d1 = {1, 10, 2023};\n  Date * d2 = &d1;\n  (*d2).day = 2;\n  Date * d3 = malloc(sizeof(Date));\n  *d3 = *d2;\n  (*d3).month = 12; (*d3).day = 11;\n  printf(\"Diff: %d/%d/%d\\n\", (*d3).day - d1.day, (*d3).month - d1.month, (*d3).year - d1.year);\n  return 0;\n}\n```",
  "hint": "Ξεχωρίστε πού δείχνει κάθε δείκτης: το `d2` σε υπάρχουσα μεταβλητή, το `d3` σε νέα\nμνήμη. Αλλάζει το `d1` όταν γράφετε μέσω του `d2`; Τι αντιγράφει το `*d3 = *d2`;"
 },
 {
  "id": "slides-lec19-field-assignment",
  "kind": "slides",
  "title": "Ανάθεση και χρήση πεδίων δομής",
  "source": {
   "title": "Διάλεξη 19, διαφάνειες 12–13",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec19.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   19
  ],
  "topics": [
   "structs",
   "strings"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α19.1",
  "path": "questions/slides/slides-lec19-field-assignment.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec19-field-assignment.html",
  "statement": "Με τη δομή\n\n```c\nstruct student {\n  char first_name[128];\n  char last_name[128];\n  unsigned int year;\n  double grade;\n};\n```\n\nτι τυπώνει αυτό το πρόγραμμα;\n\n```c\nint main() {\n  struct student st1;\n  st1.year = 1;\n  st1.grade = 7.54;\n  strncpy(st1.first_name, \"Thanos\", sizeof(st1.first_name) - 1);\n  st1.first_name[sizeof(st1.first_name) - 1] = '\\0';\n  strncpy(st1.last_name, \"Barbounis\", sizeof(st1.last_name) - 1);\n  st1.last_name[sizeof(st1.last_name) - 1] = '\\0';\n  printf(\"%s %s: %f [%u year]\\n\", st1.first_name, st1.last_name, st1.grade, st1.year);\n  return 0;\n}\n```",
  "hint": "Κάθε πεδίο συμπεριφέρεται όπως μια μεταβλητή του τύπου του. Προσέξτε πόσα δεκαδικά\nτυπώνει το `%f` χωρίς ακρίβεια."
 },
 {
  "id": "slides-lec19-many-students",
  "kind": "slides",
  "title": "Πώς αναπαριστούμε 100 φοιτητές;",
  "source": {
   "title": "Διάλεξη 19, διαφάνειες 6–7",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec19.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   19
  ],
  "topics": [
   "structs",
   "arrays"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α19.2",
  "path": "questions/slides/slides-lec19-many-students.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec19-many-students.html",
  "statement": "Για ένα πρόγραμμα διαχείρισης μιας λίστας φοιτητών θα χρειαστείτε μεταβλητές για τα\nακόλουθα:\n\n```c\nchar first_name[128];\nchar last_name[128];\nunsigned int year;\ndouble grade;\n```\n\nΈστω ότι έχουμε 100 φοιτητές, τι θα κάνουμε για να τους αναπαραστήσουμε στο\nπρόγραμμά μας;",
  "hint": "Σκεφτείτε πρώτα τη λύση μόνο με πίνακες: πόσους πίνακες χρειάζεστε και τι πρέπει να\nισχύει για τη θέση `i` σε καθέναν; Μετά σκεφτείτε πώς θα μπορούσαν τα τέσσερα πεδία\nενός φοιτητή να γίνουν ένας τύπος."
 },
 {
  "id": "slides-lec19-padding-interleaved",
  "kind": "slides",
  "title": "Padding: η σειρά των πεδίων μετράει",
  "source": {
   "title": "Διάλεξη 19, διαφάνειες 25–27",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec19.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   19
  ],
  "topics": [
   "structs",
   "memory-model"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α19.6",
  "path": "questions/slides/slides-lec19-padding-interleaved.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec19-padding-interleaved.html",
  "statement": "Τι θα τυπώσει αυτό το πρόγραμμα (μεταγλώττιση με `gcc -m32 -o struct3 struct3.c`);\n\n```c\n#include <stdio.h>\nint main() {\n  struct pixel_tag {\n     char red; int alpha;\n     char green; int beta;\n     char blue; int gamma;\n  } pixel;\n  printf(\"%zu\\n\", sizeof(pixel));\n  return 0;\n}\n```",
  "hint": "Ζωγραφίστε τη δομή byte-byte με τη σειρά της δήλωσης και βάλτε κάθε `int` σε\nδιεύθυνση πολλαπλάσιο του 4. Πόσα από τα bytes χρησιμοποιούνται στην πραγματικότητα;"
 },
 {
  "id": "slides-lec19-padding-pixel",
  "kind": "slides",
  "title": "Padding: το μέγεθος ενός pixel",
  "source": {
   "title": "Διάλεξη 19, διαφάνειες 22–24",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec19.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   19
  ],
  "topics": [
   "structs",
   "memory-model"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α19.7",
  "path": "questions/slides/slides-lec19-padding-pixel.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec19-padding-pixel.html",
  "statement": "Τι θα τυπώσει αυτό το πρόγραμμα (μεταγλώττιση με `gcc -m32 -o struct2 struct2.c`);\n\n```c\n#include <stdio.h>\nint main() {\n  struct pixel_tag {\n      char red;\n      char green;\n      char blue;\n      int alpha;\n  } pixel = {0xFF, 0xFF, 0xFF, 42};\n  printf(\"%zu\\n\", sizeof(pixel));\n  return 0;\n}\n```",
  "hint": "Τα πεδία πιάνουν 7 bytes, αλλά η απάντηση δεν είναι 7. Σκεφτείτε σε ποια διεύθυνση\nπροτιμά ο επεξεργαστής να ξεκινά ένα `int` (memory alignment)."
 },
 {
  "id": "slides-lec19-sizeof-student",
  "kind": "slides",
  "title": "Το μέγεθος του struct student",
  "source": {
   "title": "Διάλεξη 19, διαφάνειες 20–21, 28",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec19.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   19
  ],
  "topics": [
   "structs",
   "memory-model",
   "types"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α19.8",
  "path": "questions/slides/slides-lec19-sizeof-student.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec19-sizeof-student.html",
  "statement": "```c\nstruct student {\n  char first_name[128];\n  char last_name[128];\n  unsigned int year;\n  double grade;\n};\n```\n\nΤι θα τυπώσει το ακόλουθο, όταν το πρόγραμμα μεταγλωττιστεί με `gcc -m32`;\n\n```c\nprintf(\"%zu\\n\", sizeof(struct student));\n```\n\nΠοιο είναι, γενικά, το μέγεθος του `struct student`;",
  "hint": "Αθροίστε τα μεγέθη των πεδίων με τη σειρά της δήλωσης. Για το γενικό ερώτημα,\nσκεφτείτε αν ο μεταγλωττιστής είναι υποχρεωμένος να τα τοποθετήσει κολλητά (τι\nαλλάζει για ένα `double` σε σύστημα 64 bit;)."
 },
 {
  "id": "slides-lec19-struct-assign",
  "kind": "slides",
  "title": "Ανάθεση με δομές",
  "source": {
   "title": "Διάλεξη 19, διαφάνειες 29–30",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec19.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   19
  ],
  "topics": [
   "structs",
   "variables"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α19.3",
  "path": "questions/slides/slides-lec19-struct-assign.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec19-struct-assign.html",
  "statement": "Για να αντιγραφούν τα περιεχόμενα μιας δομής σε μια άλλη, χρησιμοποιούμε τον τελεστή\nανάθεσης. Τι θα τυπώσει αυτό το πρόγραμμα;\n\n```c\n#include <stdio.h>\nstruct point { int x;  int y; };\nint main() {\n  struct point pt1 = { 3, 4 };\n  struct point pt2;\n  printf(\"%d %d\\n\", pt2.x, pt2.y);\n  pt2 = pt1;\n  printf(\"%d %d\\n\", pt2.x, pt2.y);\n  return 0;\n}\n```",
  "hint": "Εξετάστε χωριστά τα δύο `printf`: τι περιέχει το `pt2` πριν από την ανάθεση, αφού\nδεν αρχικοποιήθηκε; Και τι αντιγράφει η ανάθεση ανάμεσα σε δύο δομές ίδιου τύπου;"
 },
 {
  "id": "slides-lec19-struct-compare",
  "kind": "slides",
  "title": "Σύγκριση με δομές",
  "source": {
   "title": "Διάλεξη 19, διαφάνεια 32",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec19.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   19
  ],
  "topics": [
   "structs",
   "operators"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α19.4",
  "path": "questions/slides/slides-lec19-struct-compare.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec19-struct-compare.html",
  "statement": "Μπορώ να συγκρίνω δομές με τελεστές σύγκρισης;\n\n```c\nstruct point pt1 = { 3, 4 };\nstruct point pt2;\npt2 = pt1;\nif (pt1 == pt2) printf(\"impossible\\n\");\n```",
  "hint": "Δοκιμάστε να το μεταγλωττίσετε και διαβάστε το μήνυμα του `gcc`. Αν η ανάθεση\nεπιτρέπεται, ισχύει το ίδιο για το `==`; Πώς αλλιώς μπορείτε να ελέγξετε αν δύο\nσημεία είναι ίδια;"
 },
 {
  "id": "slides-lec20-bitfield-assign",
  "kind": "slides",
  "title": "Ανάθεση σε πεδία bit",
  "source": {
   "title": "Διάλεξη 20, διαφάνεια 12",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec20.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   20
  ],
  "topics": [
   "structs",
   "unions-enums",
   "integer-representation"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α20.8",
  "path": "questions/slides/slides-lec20-bitfield-assign.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec20-bitfield-assign.html",
  "statement": "Τι θα τυπώσει το πρόγραμμα;\n\n```c\n#include <stdio.h>\n\ntypedef struct {\n  unsigned char registered : 1;\n  unsigned char year : 3;\n  unsigned char grade : 4;\n} status;\n\nint main() {\n  status st = {1, 1, 10};\n  printf(\"Status: %u %u %u\\n\", st.registered, st.year, st.grade);\n  st.year = 2;\n  printf(\"Status: %u %u %u\\n\", st.registered, st.year, st.grade);\n  st.year += 7;\n  printf(\"Status: %u %u %u\\n\", st.registered, st.year, st.grade);\n  return 0;\n}\n```",
  "hint": "Οι δύο πρώτες γραμμές είναι απλές. Για την τρίτη, σκεφτείτε ποια είναι η μεγαλύτερη\nτιμή που χωράει σε 3 bits και τι απομένει όταν κρατήσετε μόνο τα 3 χαμηλά bits\nτου αποτελέσματος."
 },
 {
  "id": "slides-lec20-bitfield-sizeof",
  "kind": "slides",
  "title": "Μέγεθος δομής με πεδία bit",
  "source": {
   "title": "Διάλεξη 20, διαφάνεια 7",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec20.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   20
  ],
  "topics": [
   "structs",
   "unions-enums"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α20.1",
  "path": "questions/slides/slides-lec20-bitfield-sizeof.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec20-bitfield-sizeof.html",
  "statement": "Τι τυπώνει το παρακάτω κομμάτι κώδικα; Τι θα τύπωνε αν οι τρεις τύποι `int` γίνονταν\n`char`; Και αν, επιπλέον, αφαιρούσαμε τα `: 1`, `: 3`, `: 4`;\n\n```c\nstruct student_status {\n  int registered : 1;\n  int year : 3;\n  int grade : 4;\n};\nprintf(\"%zu\\n\", sizeof(struct student_status));\n```",
  "hint": "Μετρήστε πόσα bits χρειάζονται συνολικά τα τρία πεδία και σκεφτείτε σε πόσες\n«μονάδες» του τύπου τους χωράνε. Χωρίς πεδία bit, κάθε μέλος πιάνει ολόκληρο τον\nτύπο του."
 },
 {
  "id": "slides-lec20-enum-loop",
  "kind": "slides",
  "title": "Βρόχος με απαρίθμηση",
  "source": {
   "title": "Διάλεξη 20, διαφάνεια 27",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec20.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   20
  ],
  "topics": [
   "unions-enums",
   "loops"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α20.2",
  "path": "questions/slides/slides-lec20-enum-loop.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec20-enum-loop.html",
  "statement": "Τι θα τυπώσει το ακόλουθο πρόγραμμα;\n\n```c\n#include <stdio.h>\n\nenum weekday {Mon = 1, Tue, Wed, Thu, Fri, Sat, Sun};\n\nint main() {\n  for (enum weekday day = Mon; day <= Sun; day++) {\n    if (day == Mon || day == Fri)\n      printf(\"We have class on day # %d of the week\\n\", day);\n  }\n  return 0;\n}\n```",
  "hint": "Βρείτε πρώτα την ακέραια τιμή κάθε σταθεράς, αφού τώρα η `Mon` έχει ρητή τιμή. Μετά\nτρέξτε τον βρόχο σαν να ήταν ένας απλός ακέραιος μετρητής."
 },
 {
  "id": "slides-lec20-enum-values",
  "kind": "slides",
  "title": "Τιμές απαρίθμησης",
  "source": {
   "title": "Διάλεξη 20, διαφάνεια 25",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec20.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   20
  ],
  "topics": [
   "unions-enums"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α20.3",
  "path": "questions/slides/slides-lec20-enum-values.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec20-enum-values.html",
  "statement": "Τι θα τυπώσει το ακόλουθο πρόγραμμα;\n\n```c\n#include <stdio.h>\n\nenum weekday {Mon, Tue, Wed, Thu, Fri, Sat, Sun};\n\nint main() {\n  enum weekday day1 = Mon, day2;\n  day2 = Fri;\n  printf(\"%d %d\\n\", day1, day2);\n  return 0;\n}\n```",
  "hint": "Θυμηθείτε από ποια τιμή ξεκινά η πρώτη σταθερά μιας απαρίθμησης όταν δεν της δίνουμε\nτιμή, και πόσο αυξάνεται κάθε επόμενη."
 },
 {
  "id": "slides-lec20-family-tree",
  "kind": "slides",
  "title": "Γενεαλογικό δέντρο",
  "source": {
   "title": "Διάλεξη 20, διαφάνεια 43",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec20.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   20,
   22
  ],
  "topics": [
   "trees",
   "structs"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α20.4",
  "path": "questions/slides/slides-lec20-family-tree.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec20-family-tree.html",
  "statement": "Δίνεται η δομή:\n\n```c\nstruct person {\n  char name[128];\n  struct person *parent1;\n  struct person *parent2;\n};\n```\n\nΜε αυτήν φτιάχνουμε το γενεαλογικό δέντρο: ο Angel δείχνει στους Logan και River, ο\nLogan στους Avery και Andie, ο River στους Hayden και Riley, κ.ο.κ. Μας θυμίζει κάτι;",
  "hint": "Κάθε κόμβος έχει το πολύ δύο δείκτες προς άλλους κόμβους του ίδιου τύπου, και\nυπάρχει ένας «πρώτος» κόμβος από τον οποίο ξεκινούν όλα. Ποια δομή δεδομένων έχει\nαυτά τα χαρακτηριστικά;"
 },
 {
  "id": "slides-lec20-filesystem-children",
  "kind": "slides",
  "title": "Σύστημα αρχείων με υποφακέλους",
  "source": {
   "title": "Διάλεξη 20, διαφάνεια 47",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec20.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   20
  ],
  "topics": [
   "structs",
   "trees",
   "pointers"
  ],
  "difficulty": 2,
  "type": "short-answer",
  "label": "Α20.9",
  "path": "questions/slides/slides-lec20-filesystem-children.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec20-filesystem-children.html",
  "statement": "Θέλω να αναπαραστήσω ένα σύστημα αρχείων (filesystem) ώστε να βρίσκω άμεσα τους\nυποφακέλους και τον parent φάκελο. Πώς;",
  "hint": "Ξεκινήστε από τη `struct folder` με όνομα και δείκτη `parent`. Τι πρέπει να\nπροσθέσετε ώστε να φτάνετε και προς τα κάτω; Ένας φάκελος μπορεί να έχει οσουσδήποτε\nυποφακέλους, οπότε σκεφτείτε μια δομή που μεγαλώνει (π.χ. δυναμικός πίνακας δεικτών\nή λίστα)."
 },
 {
  "id": "slides-lec20-folder-iterate",
  "kind": "slides",
  "title": "Διάσχιση φακέλων",
  "source": {
   "title": "Διάλεξη 20, διαφάνεια 35",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec20.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   20
  ],
  "topics": [
   "structs",
   "pointers",
   "loops"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α20.10",
  "path": "questions/slides/slides-lec20-folder-iterate.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec20-folder-iterate.html",
  "statement": "Τι θα τυπώσει το πρόγραμμα;\n\n```c\n#include <stdio.h>\n\ntypedef struct folder {\n  char name[128];\n  struct folder *parent;\n} Folder;\n\nint main() {\n  Folder root = {\"/\", NULL};\n  Folder home = {\"home/\", &root};\n  Folder user = {\"thanos/\", &home};\n  Folder hw0 = {\"hw0/\", &user}, hw1 = {\"hw1/\", &user};\n  Folder newton = {\"newton/\", &hw0};\n  for (Folder *iterator = &newton; iterator; iterator = iterator->parent)\n    printf(\"folder: %s\\n\", iterator->name);\n  return 0;\n}\n```",
  "hint": "Ο βρόχος ξεκινά με δείκτη στον `newton` και σε κάθε βήμα μετακινείται στον γονέα.\nΡωτήστε: πότε γίνεται ψευδής η συνθήκη `iterator`; Τυπώνεται ποτέ ο `hw1`;"
 },
 {
  "id": "slides-lec20-folder-parent",
  "kind": "slides",
  "title": "Γονικοί φάκελοι",
  "source": {
   "title": "Διάλεξη 20, διαφάνεια 33",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec20.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   20
  ],
  "topics": [
   "structs",
   "pointers"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α20.5",
  "path": "questions/slides/slides-lec20-folder-parent.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec20-folder-parent.html",
  "statement": "Τι θα τυπώσει το πρόγραμμα;\n\n```c\n#include <stdio.h>\n\ntypedef struct folder {\n  char name[128];\n  struct folder *parent;\n} Folder;\n\nint main() {\n  Folder root = {\"/\", NULL};\n  Folder home = {\"home/\", &root};\n  Folder user = {\"thanos/\", &home};\n  Folder hw0 = {\"hw0/\", &user}, hw1 = {\"hw1/\", &user};\n  Folder newton = {\"newton/\", &hw0};\n  printf(\"%s -> %s -> %s\\n\", newton.name, newton.parent->name,\n         newton.parent->parent->name);\n  return 0;\n}\n```",
  "hint": "Ακολουθήστε τους δείκτες `parent` ένα βήμα κάθε φορά, ξεκινώντας από τον `newton`.\nΓράψτε δίπλα σε κάθε φάκελο σε ποια μεταβλητή δείχνει."
 },
 {
  "id": "slides-lec20-folder-struct",
  "kind": "slides",
  "title": "Δομή για φάκελο",
  "source": {
   "title": "Διάλεξη 20, διαφάνεια 31",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec20.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   20
  ],
  "topics": [
   "structs",
   "pointers"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α20.6",
  "path": "questions/slides/slides-lec20-folder-struct.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec20-folder-struct.html",
  "statement": "Θέλω να φτιάξω μια δομή (struct) που να αναπαριστά έναν φάκελο σε ένα σύστημα\nαρχείων. Πώς θα το κάνω;\n\nΚάθε φάκελος έχει ένα όνομα και βρίσκεται μέσα σε κάποιον άλλο (parent) φάκελο. Ο\nαρχικός φάκελος (root `/`) δεν βρίσκεται μέσα σε κάποιο φάκελο. Για παράδειγμα:\n`/` → `home/` → `thanos/` → `hw0/`, `hw1/`, `hw2/`, και `hw0/` → `newton/` → `src/`.",
  "hint": "Χρειάζεστε ένα μέλος για το όνομα και ένα μέλος που να «δείχνει» στον γονικό φάκελο.\nΣκεφτείτε γιατί αυτό το μέλος δεν μπορεί να είναι ολόκληρη δομή του ίδιου τύπου,\nκαι τι τιμή πρέπει να έχει για τη ρίζα."
 },
 {
  "id": "slides-lec20-graph-map",
  "kind": "slides",
  "title": "Χάρτης ως γράφος",
  "source": {
   "title": "Διάλεξη 20, διαφάνεια 46",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec20.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   20
  ],
  "topics": [
   "graphs",
   "structs",
   "pointers"
  ],
  "difficulty": 3,
  "type": "short-answer",
  "label": "Α20.12",
  "path": "questions/slides/slides-lec20-graph-map.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec20-graph-map.html",
  "statement": "Θέλω να αναπαραστήσω έναν χάρτη σε μορφή γράφου με αυτοαναφορικές δομές. Πώς;\n\nΟ χάρτης έχει τέσσερις κόμβους A, B, C, D και κάθε ζεύγος συνδέεται με ακμή που έχει\nβάρος (απόσταση): A–B 20, A–C 42, A–D 35, B–C 30, B–D 34, C–D 12.",
  "hint": "Σκεφτείτε τι πρέπει να κρατά κάθε κόμβος: ένα όνομα και τους γείτονές του. Επειδή σε\nέναν γράφο το πλήθος των γειτόνων δεν είναι σταθερό και κάθε ακμή έχει βάρος, δεν\nαρκεί ένας σταθερός αριθμός δεικτών όπως στη λίστα ή στο δυαδικό δέντρο."
 },
 {
  "id": "slides-lec20-list-layout",
  "kind": "slides",
  "title": "Η διάταξη των φακέλων",
  "source": {
   "title": "Διάλεξη 20, διαφάνεια 38",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec20.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   20,
   21
  ],
  "topics": [
   "linked-lists",
   "structs"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α20.7",
  "path": "questions/slides/slides-lec20-list-layout.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec20-list-layout.html",
  "statement": "Η πραγματική διάταξη (layout) των φακέλων `newton/`, `hw0/`, `thanos/`, `home/`, `/`\nστη μνήμη μπορεί να είναι περίπλοκη. Σε αφηρημένη μορφή είναι κάπως έτσι:\n\n```text\n\"newton\" | &hw0  ->  \"hw0\" | &user  ->  \"thanos\" | &home\n  ->  \"home/\" | &root  ->  \"/\" | NULL\n```\n\nΜας θυμίζει κάτι αυτή η διάταξη;",
  "hint": "Κάθε στοιχείο κρατά μια τιμή και δείχνει στο επόμενο, και το τελευταίο δείχνει στο\n`NULL`. Ποια δομή δεδομένων ορίζεται ακριβώς έτσι;"
 },
 {
  "id": "slides-lec20-union-size",
  "kind": "slides",
  "title": "Χρήση ένωσης και μέγεθος",
  "source": {
   "title": "Διάλεξη 20, διαφάνεια 19",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec20.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   20
  ],
  "topics": [
   "unions-enums",
   "memory-model"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α20.11",
  "path": "questions/slides/slides-lec20-union-size.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec20-union-size.html",
  "statement": "Τι θα τυπώσει το πρόγραμμα;\n\n```c\n#include <stdio.h>\n\nunion anything {\n  char c;  int i;  float f;  double d;\n};\n\nint main() {\n  union anything a1;\n  a1.i = 0x42;\n  printf(\"%d %c\\n\", a1.i, a1.c);\n  a1.c = 'C';\n  printf(\"%d %c\\n\", a1.i, a1.c);\n  printf(\"%zu\\n\", sizeof(a1));\n  return 0;\n}\n```",
  "hint": "Όλα τα μέλη της ένωσης ξεκινούν από το ίδιο byte, οπότε το `c` είναι το πρώτο byte\nτου `i`. Σκεφτείτε ποιο byte ενός ακεραίου είναι πρώτο σε ένα little-endian\nμηχάνημα, και ότι το μέγεθος της ένωσης καθορίζεται από το μεγαλύτερο μέλος."
 },
 {
  "id": "slides-lec21-delete-how",
  "kind": "slides",
  "title": "Αφαίρεση στοιχείου από λίστα",
  "source": {
   "title": "Διάλεξη 21, διαφάνειες 23–25",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec21.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   21
  ],
  "topics": [
   "linked-lists",
   "pointers",
   "dynamic-memory"
  ],
  "difficulty": 2,
  "type": "short-answer",
  "label": "Α21.4",
  "path": "questions/slides/slides-lec21-delete-how.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec21-delete-how.html",
  "statement": "Δίνεται η απλά συνδεδεμένη λίστα:\n\n```text\nlist -> 5 -> 6 -> 7 -> 8 -> NULL\n```\n\nΘέλω να αφαιρέσω ένα στοιχείο (π.χ., το 6). Πως;",
  "hint": "Ποιος δείκτης δείχνει σήμερα στον κόμβο 6, και πού πρέπει να δείχνει μετά την αφαίρεση; Τι γίνεται με τη μνήμη του κόμβου; Σκεφτείτε ξεχωριστά την περίπτωση που το στοιχείο είναι η κεφαλή: γιατί η συνάρτηση χρειάζεται `List *` και όχι `List`;"
 },
 {
  "id": "slides-lec21-find-output",
  "kind": "slides",
  "title": "Τι τυπώνει η find σε λίστα;",
  "source": {
   "title": "Διάλεξη 21, διαφάνειες 21–22",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec21.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   21
  ],
  "topics": [
   "linked-lists",
   "pointers",
   "complexity"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α21.5",
  "path": "questions/slides/slides-lec21-find-output.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec21-find-output.html",
  "statement": "Τι θα τυπώσει το πρόγραμμα; (Η `insert` είναι η εισαγωγή στην αρχή της λίστας της διάλεξης.)\n\n```c\n#include <stdio.h>\n#include <stdlib.h>\ntypedef struct listnode {int value; struct listnode * next;} * List;\nList find(List list, int value) {\n  while(list && list->value != value) {\n    list = list->next;\n  }\n  return list;\n}\nint main() {\n  List list = NULL;\n  insert(&list, 42); insert(&list, 43); insert(&list, 44);\n  printf(\"Found 43: %x\\n\", find(list, 43));\n  printf(\"Found 34: %x\\n\", find(list, 34));\n  return 0;\n}\n```\n\nΠοια η πολυπλοκότητα της `find` ως προς χρόνο και χώρο;",
  "hint": "Τι επιστρέφει η `find` όταν βρει την τιμή και τι όταν φτάσει στο τέλος της λίστας; Η μία από τις δύο γραμμές δεν μπορεί να προβλεφθεί ακριβώς: γιατί; Σκεφτείτε επίσης αν το `%x` είναι ο σωστός προσδιοριστής για δείκτη."
 },
 {
  "id": "slides-lec21-insert-how",
  "kind": "slides",
  "title": "Προσθήκη στοιχείου σε λίστα",
  "source": {
   "title": "Διάλεξη 21, διαφάνειες 11–12",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec21.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   21
  ],
  "topics": [
   "linked-lists",
   "pointers",
   "dynamic-memory"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α21.1",
  "path": "questions/slides/slides-lec21-insert-how.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec21-insert-how.html",
  "statement": "Δίνεται η απλά συνδεδεμένη λίστα:\n\n```text\nlist -> 6 -> 7 -> 8 -> NULL\n```\n\nΘέλω να προσθέσω ένα στοιχείο (π.χ., το 5) σε λίστα. Πως;",
  "hint": "Σκεφτείτε πού είναι φθηνότερο να μπει ο νέος κόμβος, ώστε να μη χρειαστεί να διασχίσετε τη λίστα. Ποιοι δείκτες πρέπει να αλλάξουν, και με ποια σειρά, ώστε να μη χαθεί κανένας κόμβος; Από πού θα πάρετε μνήμη για τον νέο κόμβο;"
 },
 {
  "id": "slides-lec21-insert-output",
  "kind": "slides",
  "title": "Τι τυπώνει η εισαγωγή σε λίστα;",
  "source": {
   "title": "Διάλεξη 21, διαφάνειες 13–16",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec21.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   21
  ],
  "topics": [
   "linked-lists",
   "dynamic-memory",
   "pointers"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α21.2",
  "path": "questions/slides/slides-lec21-insert-output.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec21-insert-output.html",
  "statement": "Τι θα τυπώσει το πρόγραμμα;\n\n```c\n#include <stdio.h>\n#include <stdlib.h>\ntypedef struct listnode {int value; struct listnode * next;} * List;\nvoid insert(List * list, int value) {\n  List current_head = *list;\n  List new_head = malloc(sizeof(struct listnode));\n  new_head->value = value;\n  new_head->next = current_head;\n  *list = new_head;\n}\nvoid print(List list) {\n  printf(\"list: \");\n  while(list) {\n    printf(\" -> %d\", list->value);\n    list = list->next;\n  }\n  printf(\" -> NULL\\n\");\n}\nint main() {\n  List list = NULL;\n  insert(&list, 42); insert(&list, 43); insert(&list, 44);\n  print(list);\n  return 0;\n}\n```",
  "hint": "Ζωγραφίστε τη λίστα μετά από κάθε κλήση της `insert`: σε ποια θέση μπαίνει κάθε νέος κόμβος; Προσέξτε και τα κενά που τυπώνουν τα δύο πρώτα `printf`."
 },
 {
  "id": "slides-lec21-length-complexity",
  "kind": "slides",
  "title": "Πολυπλοκότητα του μήκους λίστας",
  "source": {
   "title": "Διάλεξη 21, διαφάνειες 19–20",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec21.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   21
  ],
  "topics": [
   "complexity",
   "linked-lists",
   "recursion"
  ],
  "difficulty": 2,
  "type": "short-answer",
  "label": "Α21.6",
  "path": "questions/slides/slides-lec21-length-complexity.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec21-length-complexity.html",
  "statement": "Δίνονται δύο υλοποιήσεις της `length`:\n\n```c\nint length(List list) {\n  int counter = 0;\n  while(list) {\n    counter++;\n    list = list->next;\n  }\n  return counter;\n}\n```\n\n```c\nint length(List list) {\n  if (!list) return 0;\n  return 1 + length(list->next);\n}\n```\n\nΠοια η πολυπλοκότητα των παραπάνω ως προς χρόνο και χώρο;",
  "hint": "Για τον χρόνο, μετρήστε πόσες φορές επισκέπτεται κάθε εκδοχή κάθε κόμβο. Για τον χώρο, σκεφτείτε πόσες κλήσεις της συνάρτησης είναι ταυτόχρονα ενεργές στη στοίβα όταν φτάνουμε στο τέλος της λίστας."
 },
 {
  "id": "slides-lec21-recursive-length",
  "kind": "slides",
  "title": "Αναδρομικό μήκος λίστας",
  "source": {
   "title": "Διάλεξη 21, διαφάνεια 18",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec21.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   21
  ],
  "topics": [
   "linked-lists",
   "recursion"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α21.3",
  "path": "questions/slides/slides-lec21-recursive-length.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec21-recursive-length.html",
  "statement": "Η παρακάτω συνάρτηση βρίσκει το μήκος μιας λίστας επαναληπτικά:\n\n```c\nint length(List list) {\n  int counter = 0;\n  while(list) {\n    counter++;\n    list = list->next;\n  }\n  return counter;\n}\n```\n\nΠως θα το κάναμε αναδρομικά;",
  "hint": "Ποιο είναι το μήκος της κενής λίστας (`NULL`); Αν ξέρατε το μήκος της λίστας που ξεκινά από το `list->next`, πώς θα βρίσκατε το μήκος ολόκληρης της λίστας;"
 },
 {
  "id": "slides-lec22-best-search",
  "kind": "slides",
  "title": "Ποιος αλγόριθμος αναζήτησης είναι καλύτερος;",
  "source": {
   "title": "Διαλέξεις 21–22: Δέντρα, διαφάνεια 38 (διάλεξη 21: διαφάνεια 60)",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec22.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   22,
   21
  ],
  "topics": [
   "trees",
   "graphs"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α22.1",
  "path": "questions/slides/slides-lec22-best-search.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec22-best-search.html",
  "statement": "Ποιος αλγόριθμος αναζήτησης είναι καλύτερος; Η αναζήτηση κατά βάθος (DFS) ή η\nαναζήτηση κατά πλάτος (BFS);",
  "hint": "Συγκρίνετε τη σειρά με την οποία επισκέπτεται τους κόμβους ο καθένας και πόση προσωρινή μνήμη χρειάζεται (τη στοίβα της αναδρομής έναντι του μετώπου). Σκεφτείτε ένα πρόβλημα όπου πλεονεκτεί ο καθένας."
 },
 {
  "id": "slides-lec22-bst-exists",
  "kind": "slides",
  "title": "Έλεγχος ύπαρξης σε δυαδικό δέντρο αναζήτησης",
  "source": {
   "title": "Διαλέξεις 21–22: Δέντρα, διαφάνειες 35–37 (διάλεξη 21: διαφάνειες 57–59)",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec22.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   22,
   21
  ],
  "topics": [
   "trees",
   "searching",
   "recursion"
  ],
  "difficulty": 1,
  "type": "programming",
  "label": "Α22.2",
  "path": "questions/slides/slides-lec22-bst-exists.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec22-bst-exists.html",
  "statement": "Ένα Δυαδικό Δέντρο Αναζήτησης (Binary Search Tree - BST ή Ordered Tree) είναι ένα\nταξινομημένο δέντρο έτσι ώστε για κάθε κόμβο, όλοι οι κόμβοι στο αριστερό του υποδέντρο\nνα είναι μικρότεροι σε τιμή και όλοι οι κόμβοι στο δεξί του υποδέντρο να είναι\nμεγαλύτεροι.\n\nΈλεγχος αν υπάρχει (exists) ένα στοιχείο σε δυαδικό δέντρο. Πως;\n\nΓράψτε τη συνάρτηση\n\n```c\nint exists(Tree t, int value);\n```\n\nπου επιστρέφει 1 αν η τιμή `value` υπάρχει στο BST `t` και 0 αλλιώς, με χρόνο\n$O(\\log n)$ για ισορροπημένο δέντρο.",
  "hint": "Σε κάθε κόμβο, η σύγκριση του `value` με την τιμή του κόμβου σας λέει σε ποιο από τα δύο υποδέντρα *μπορεί* να βρίσκεται η τιμή· το άλλο δεν χρειάζεται να το ψάξετε. Μην ξεχάσετε τη βασική περίπτωση του άδειου δέντρου."
 },
 {
  "id": "slides-lec22-depth-complexity",
  "kind": "slides",
  "title": "Πολυπλοκότητα της depth",
  "source": {
   "title": "Διαλέξεις 21–22: Δέντρα, διαφάνεια 20 (διάλεξη 21: διαφάνειες 41–42)",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec22.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   22,
   21
  ],
  "topics": [
   "trees",
   "recursion",
   "complexity"
  ],
  "difficulty": 2,
  "type": "short-answer",
  "label": "Α22.6",
  "path": "questions/slides/slides-lec22-depth-complexity.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec22-depth-complexity.html",
  "statement": "Δίνεται η συνάρτηση που υπολογίζει το βάθος ενός δυαδικού δέντρου:\n\n```c\nint depth(Tree t) {\n  if (t == NULL) return -1;\n  int left_depth = depth(t->left);\n  int right_depth = depth(t->right);\n  return 1 + ((left_depth > right_depth) ? left_depth : right_depth);\n}\n```\n\nΠοια η πολυπλοκότητα για ένα τέλειο δυαδικό δέντρο; (χρόνος και χώρος)",
  "hint": "Για τον χρόνο, μετρήστε πόσες φορές καλείται η `depth` για κάθε κόμβο. Για τον χώρο, σκεφτείτε πόσες κλήσεις μπορεί να βρίσκονται ταυτόχρονα στη στοίβα, και πώς σχετίζεται αυτό με το ύψος ενός τέλειου δέντρου με $n$ κόμβους."
 },
 {
  "id": "slides-lec22-expression-evaluator",
  "kind": "slides",
  "title": "Διάσχιση για αποτιμητή εκφράσεων",
  "source": {
   "title": "Διαλέξεις 21–22: Δέντρα, διαφάνεια 29 (διάλεξη 21: διαφάνεια 51)",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec22.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   22,
   21
  ],
  "topics": [
   "trees",
   "recursion"
  ],
  "difficulty": 2,
  "type": "short-answer",
  "label": "Α22.7",
  "path": "questions/slides/slides-lec22-expression-evaluator.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec22-expression-evaluator.html",
  "statement": "Θέλω να γράψω έναν αποτιμητή εκφράσεων (calculator / evaluator / interpreter). Ποια\nδιάσχιση θα χρησιμοποιήσω;\n\nΤο δέντρο της διαφάνειας έχει ρίζα `+`· το αριστερό παιδί του είναι `*` (με παιδιά `2`\nκαι `9`) και το δεξί είναι `1`.\n\n```mermaid\nflowchart TD\n  P((\"+\")) --> M((\"*\"))\n  P --> O((\"1\"))\n  M --> T((\"2\"))\n  M --> N((\"9\"))\n```",
  "hint": "Για να υπολογίσετε τον τελεστή ενός κόμβου χρειάζεστε ήδη τις τιμές των δύο υποδέντρων του. Ποια από τις τρεις διασχίσεις (pre-order, in-order, post-order) επεξεργάζεται τον κόμβο αφού έχει τελειώσει με τα παιδιά του;"
 },
 {
  "id": "slides-lec22-generic-list",
  "kind": "slides",
  "title": "Λίστα για το BFS και λίστες κάθε τύπου",
  "source": {
   "title": "Διαλέξεις 21–22: Δέντρα, διαφάνεια 33 (διάλεξη 21: διαφάνεια 55)",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec22.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   22,
   21
  ],
  "topics": [
   "linked-lists",
   "trees",
   "pointers"
  ],
  "difficulty": 2,
  "type": "short-answer",
  "label": "Α22.8",
  "path": "questions/slides/slides-lec22-generic-list.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec22-generic-list.html",
  "statement": "Δίνεται η συνάρτηση που τυπώνει ένα δέντρο με διάσχιση κατά πλάτος (BFS):\n\n```c\nvoid bfs(Tree t) {\n  List worklist = NULL;\n  Tree tmp;\n  insert(&worklist, t);\n  while(worklist) {\n    tmp = pop_last(&worklist);\n    printf(\"%d \", tmp->value);\n    if (tmp->left) insert(&worklist, tmp->left);\n    if (tmp->right) insert(&worklist, tmp->right);\n  }\n}\n```\n\nΣημείωση: Ο τύπος List παραπάνω δεν περιέχει πλέον ακεραίους. Τι περιέχει; Πως θα\nέπρεπε να αλλάξει προκειμένου να υποστηρίξει μια τέτοια υλοποίηση; Τι θα κάνατε ώστε\nοι λίστες σας να δουλεύουν με κάθε τύπου δεδομένα;",
  "hint": "Κοιτάξτε τον τύπο του δεύτερου ορίσματος της `insert` και της τιμής που επιστρέφει η `pop_last`. Για το τελευταίο ερώτημα, σκεφτείτε έναν τύπο δείκτη της C που μπορεί να δείχνει σε δεδομένα οποιουδήποτε τύπου, και διαβάστε για τους αφηρημένους τύπους δεδομένων (ΑΤΔ)."
 },
 {
  "id": "slides-lec22-maze-shortest-path",
  "kind": "slides",
  "title": "Συντομότερο μονοπάτι σε δέντρα-λαβύρινθους: BFS ή DFS;",
  "source": {
   "title": "Διαλέξεις 21–22: Δέντρα, διαφάνεια 40 (διάλεξη 21: διαφάνεια 62)",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec22.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   22,
   21
  ],
  "topics": [
   "graphs",
   "trees"
  ],
  "difficulty": 2,
  "type": "short-answer",
  "label": "Α22.9",
  "path": "questions/slides/slides-lec22-maze-shortest-path.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec22-maze-shortest-path.html",
  "statement": "Γράφεις ένα πρόγραμμα που βρίσκει λύσεις σε δέντρα-λαβυρίνθους. Αναζητάς το\nσυντομότερο μονοπάτι για την έξοδο. BFS ή DFS; Γιατί;",
  "hint": "Σκεφτείτε με ποια σειρά απόστασης από την αρχή επισκέπτεται τους κόμβους ο κάθε αλγόριθμος. Όταν ο καθένας βρει για πρώτη φορά μια έξοδο, είναι εγγυημένα η πιο κοντινή;"
 },
 {
  "id": "slides-lec22-perfect-tree-nodes",
  "kind": "slides",
  "title": "Κόμβοι τέλειου δυαδικού δέντρου",
  "source": {
   "title": "Διαλέξεις 21–22: Δέντρα, διαφάνεια 10 (διάλεξη 21: διαφάνεια 32)",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec22.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   22,
   21
  ],
  "topics": [
   "trees"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α22.3",
  "path": "questions/slides/slides-lec22-perfect-tree-nodes.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec22-perfect-tree-nodes.html",
  "statement": "Ένα **τέλειο δυαδικό δέντρο** (perfect binary tree) είναι ένα δυαδικό δέντρο που όλοι οι\nεσωτερικοί κόμβοι έχουν δύο παιδιά και όλα τα φύλλα βρίσκονται στο ίδιο επίπεδο\n(η ρίζα βρίσκεται στο επίπεδο 1).\n\nΠόσοι κόμβοι σε $n$ επίπεδα;",
  "hint": "Μετρήστε πόσους κόμβους έχει κάθε επίπεδο ξεχωριστά: πόσους έχει το επίπεδο 1, πόσους το 2, και πώς σχετίζεται κάθε επίπεδο με το προηγούμενο; Μετά αθροίστε τη γεωμετρική πρόοδο."
 },
 {
  "id": "slides-lec22-petabyte",
  "kind": "slides",
  "title": "Αποθήκευση και αναζήτηση σε 1 PetaByte",
  "source": {
   "title": "Διαλέξεις 21–22: Δέντρα, διαφάνεια 39 (διάλεξη 21: διαφάνεια 61)",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec22.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   22,
   21
  ],
  "topics": [
   "trees",
   "searching",
   "complexity"
  ],
  "difficulty": 2,
  "type": "short-answer",
  "label": "Α22.10",
  "path": "questions/slides/slides-lec22-petabyte.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec22-petabyte.html",
  "statement": "Έχεις να αποθηκεύσεις 1 PetaByte ($10^6$ GB) δεδομένων για μια υπηρεσία (service). Πως\nθα αποθηκεύσεις τα δεδομένα σου; Πως θα κάνεις αναζήτηση;",
  "hint": "Υπολογίστε πόσα βήματα θα χρειαζόταν μια σειριακή αναζήτηση σε τέτοιο όγκο και συγκρίνετε με μια δομή όπου κάθε σύγκριση απορρίπτει το μισό των δεδομένων. Σκεφτείτε επίσης τι γίνεται όταν προστίθενται νέα δεδομένα."
 },
 {
  "id": "slides-lec22-tictactoe-tree",
  "kind": "slides",
  "title": "Δέντρο καταστάσεων τρίλιζας",
  "source": {
   "title": "Διάλεξη 22: Δέντρα, διαφάνεια 15",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec22.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   22
  ],
  "topics": [
   "trees",
   "game-ai"
  ],
  "difficulty": 2,
  "type": "short-answer",
  "label": "Α22.11",
  "path": "questions/slides/slides-lec22-tictactoe-tree.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec22-tictactoe-tree.html",
  "statement": "Είναι συνηθισμένο να αναπαριστούμε καταστάσεις χρησιμοποιώντας δομές όπως τα δέντρα,\nκάποιες φορές με **περισσότερα** από 2 παιδιά κόμβους. Η διαφάνεια δείχνει ένα δέντρο\nκαταστάσεων για την τρίλιζα (tic-tac-toe): η ρίζα είναι μια θέση του παιχνιδιού, κάθε\nπαιδί είναι η θέση μετά από μία κίνηση, και τα φύλλα έχουν βαθμολογία (+10, -10 ή 0).\n\nΑυτό το δέντρο καταστάσεων είναι σωστό ή έχει σφάλματα; Πως θα τα βρίσκαμε με έναν\nαλγόριθμο αυτόματα;",
  "hint": "Σκεφτείτε ποιες σχέσεις πρέπει να ισχύουν ανάμεσα σε έναν κόμβο και κάθε παιδί του (πόσα σύμβολα προστίθενται, ποιος παίκτης παίζει, αν αλλάζουν τα ήδη γεμάτα τετράγωνα) και ποια βαθμολογία πρέπει να έχει κάθε φύλλο. Ένας αλγόριθμος μπορεί να επισκεφθεί κάθε κόμβο με μια διάσχιση του δέντρου και να ελέγξει αυτούς τους κανόνες τοπικά."
 },
 {
  "id": "slides-lec22-traversals",
  "kind": "slides",
  "title": "Διασχίσεις pre-order, in-order, post-order",
  "source": {
   "title": "Διαλέξεις 21–22: Δέντρα, διαφάνειες 22–28 (διάλεξη 21: διαφάνειες 44–50)",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec22.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   22,
   21
  ],
  "topics": [
   "trees",
   "recursion"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α22.4",
  "path": "questions/slides/slides-lec22-traversals.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec22-traversals.html",
  "statement": "Δίνεται το δέντρο με ρίζα το 5· τα παιδιά του 5 είναι το 7 (αριστερά) και το 1 (δεξιά),\nκαι τα παιδιά του 7 είναι το 2 (αριστερά) και το 9 (δεξιά).\n\n```mermaid\nflowchart TD\n  N5((\"5\")) --> N7((\"7\"))\n  N5 --> N1((\"1\"))\n  N7 --> N2((\"2\"))\n  N7 --> N9((\"9\"))\n```\n\nΤι τυπώνει καθεμία από τις παρακάτω εκδοχές της `print` όταν καλείται με τη ρίζα;\n\n```c\nvoid print(Tree t) {       /* Pre-order */\n  if (t == NULL) return;\n  printf(\"%d \", t->value);\n  print(t->left);\n  print(t->right);\n}\n```\n\n```c\nvoid print(Tree t) {       /* In-order */\n  if (t == NULL) return;\n  print(t->left);\n  printf(\"%d \", t->value);\n  print(t->right);\n}\n```\n\n```c\nvoid print(Tree t) {       /* Post-order */\n  if (t == NULL) return;\n  print(t->left);\n  print(t->right);\n  printf(\"%d \", t->value);\n}\n```",
  "hint": "Εφαρμόστε τον ορισμό αναδρομικά, ξεκινώντας από τη ρίζα: η διάσχιση του 5 αποτελείται από τη διάσχιση του υποδέντρου του 7, τη διάσχιση του υποδέντρου του 1 και το ίδιο το 5, με τη σειρά που ορίζει η θέση του `printf`."
 },
 {
  "id": "slides-lec22-tree-delete",
  "kind": "slides",
  "title": "Αφαίρεση στοιχείου από δυαδικό δέντρο",
  "source": {
   "title": "Διαλέξεις 21–22: Δέντρα, διαφάνεια 16 (διάλεξη 21: διαφάνεια 38)",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec22.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   22,
   21
  ],
  "topics": [
   "trees",
   "dynamic-memory",
   "recursion"
  ],
  "difficulty": 3,
  "type": "programming",
  "label": "Α22.13",
  "path": "questions/slides/slides-lec22-tree-delete.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec22-tree-delete.html",
  "statement": "Στις βασικές λειτουργίες με δυαδικά δέντρα, η διάλεξη αφήνει ως άσκηση:\n\n- delete: Αφαίρεση στοιχείου από δέντρο (μόνοι σας)\n\nΥλοποιήστε την αφαίρεση μιας τιμής από δυαδικό δέντρο αναζήτησης (BST), ώστε το δέντρο\nνα παραμένει ταξινομημένο και η μνήμη του κόμβου που αφαιρείται να αποδεσμεύεται.",
  "hint": "Χωρίστε σε περιπτώσεις ανάλογα με το πόσα παιδιά έχει ο κόμβος που αφαιρείται: 0, 1 ή 2. Στην τελευταία, σκεφτείτε ποια τιμή του δέντρου μπορεί να πάρει τη θέση του χωρίς να χαλάσει η διάταξη (κοιτάξτε το δεξί υποδέντρο του)."
 },
 {
  "id": "slides-lec22-tree-insert",
  "kind": "slides",
  "title": "Προσθήκη στοιχείου σε δυαδικό δέντρο",
  "source": {
   "title": "Διαλέξεις 21–22: Δέντρα, διαφάνεια 16 (διάλεξη 21: διαφάνεια 38)",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec22.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   22,
   21
  ],
  "topics": [
   "trees",
   "dynamic-memory",
   "recursion"
  ],
  "difficulty": 2,
  "type": "programming",
  "label": "Α22.12",
  "path": "questions/slides/slides-lec22-tree-insert.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec22-tree-insert.html",
  "statement": "Στις βασικές λειτουργίες με δυαδικά δέντρα, η διάλεξη αφήνει ως άσκηση:\n\n- insert: Προσθήκη στοιχείου στο δέντρο (μόνοι σας)\n\nΥλοποιήστε την προσθήκη ενός ακεραίου σε δυαδικό δέντρο αναζήτησης (BST) με κόμβους\n\n```c\ntypedef struct treenode {\n  int value;\n  struct treenode *left;\n  struct treenode *right;\n} *Tree;\n```\n\nώστε το δέντρο να παραμένει ταξινομημένο. Ελέγξτε το αποτέλεσμα τυπώνοντας το δέντρο\nμε in-order διάσχιση.",
  "hint": "Ακολουθήστε την ίδια διαδρομή με την αναζήτηση στο BST· όταν φτάσετε σε `NULL`, εκεί ανήκει ο νέος κόμβος, που δεσμεύεται με `malloc`. Για να αλλάξει ο δείκτης του γονιού (ή η ρίζα, αν το δέντρο είναι άδειο), είτε επιστρέψτε το νέο δέντρο είτε περάστε δείκτη σε `Tree`, όπως στην `insert` των λιστών."
 },
 {
  "id": "slides-lec22-tree-max",
  "kind": "slides",
  "title": "Μέγιστο στοιχείο δέντρου: BFS ή DFS;",
  "source": {
   "title": "Διαλέξεις 21–22: Δέντρα, διαφάνεια 41 (διάλεξη 21: διαφάνεια 63)",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec22.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   22,
   21
  ],
  "topics": [
   "graphs",
   "trees"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α22.5",
  "path": "questions/slides/slides-lec22-tree-max.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec22-tree-max.html",
  "statement": "Θέλεις να βρεις το μέγιστο στοιχείο ενός δέντρου. Προτιμάς BFS ή DFS; Γιατί;",
  "hint": "Χρειάζεται να επισκεφθείτε όλους τους κόμβους ούτως ή άλλως, άρα ο χρόνος είναι ίδιος. Συγκρίνετε λοιπόν την προσωρινή μνήμη που χρειάζεται ο καθένας και πόσο απλός είναι ο κώδικας."
 },
 {
  "id": "slides-lec23-const-violations",
  "kind": "slides",
  "title": "Αλλάζοντας κάτι const",
  "source": {
   "title": "Διάλεξη 23, διαφάνειες 23-24",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec23.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   23
  ],
  "topics": [
   "variables",
   "pointers",
   "undefined-behavior"
  ],
  "difficulty": 2,
  "type": "trace",
  "label": "Α23.3",
  "path": "questions/slides/slides-lec23-const-violations.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec23-const-violations.html",
  "statement": "Τι θα συμβεί όταν μεταγλωττίσουμε και τρέξουμε καθένα από τα δύο προγράμματα; Σε\nποιο στάδιο (μεταγλώττιση ή εκτέλεση) εμφανίζεται το πρόβλημα, και γιατί;\n\n`const1.c`:\n\n```c\nconst char message[] = \"Hello\";\nint main() {\n  const int x = 42;\n  const char const * msg_ptr = message;\n  x++;\n  return 0;\n}\n```\n\n`const2.c`:\n\n```c\nconst char message[] = \"Hello\";\nint main() {\n  const int x = 42;\n  char * bad = (char*)message;\n  bad[1] = 'o';\n  return 0;\n}\n```",
  "hint": "Στο πρώτο πρόγραμμα, ο μεταγλωττιστής ξέρει ότι το `x` είναι `const`: τι θα κάνει\nμε το `x++`; Στο δεύτερο, το cast κρύβει το `const` από τον μεταγλωττιστή, όμως ο\nπίνακας `message` εξακολουθεί να βρίσκεται σε μνήμη που προορίζεται μόνο για ανάγνωση."
 },
 {
  "id": "slides-lec23-dependencies",
  "kind": "slides",
  "title": "Εξαρτήσεις ανάμεσα σε αρχεία",
  "source": {
   "title": "Διαλέξεις 23–24, διαφάνεια 15 (διάλεξη 24: διαφάνεια 16)",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec23.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   23,
   24
  ],
  "topics": [
   "code-organization",
   "compilation",
   "make"
  ],
  "difficulty": 2,
  "type": "short-answer",
  "label": "Α23.4",
  "path": "questions/slides/slides-lec23-dependencies.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec23-dependencies.html",
  "statement": "Ένα πρόγραμμα έχει τρία αρχεία:\n\n```c\n/* err.c */\nint print_err(char *msg) {\n  ...\n}\n```\n\n```c\n/* err.h */\nint print_err(char *);\n```\n\n```c\n/* init.c */\n#include \"err.h\"\n...\nprint_err(\"hi\");\n```\n\nΤο `err.c` υλοποιεί τη διεπαφή `err.h` και το `init.c` τη χρησιμοποιεί.\n\n1. Αν αλλάξω ένα αρχείο, τι επηρεάζεται; Απαντήστε για καθένα από τα τρία αρχεία.\n2. Με τι μοιάζουν αυτές οι εξαρτήσεις;",
  "hint": "Για κάθε αρχείο, αναρωτηθείτε ποια άλλα αρχεία «βλέπουν» το περιεχόμενό του κατά τη\nμεταγλώττιση. Σχεδιάστε τα αρχεία ως κόμβους και τις σχέσεις «υλοποιεί» και\n«χρησιμοποιεί» ως βέλη: ποια δομή δεδομένων από τις προηγούμενες διαλέξεις\nσχηματίζεται;"
 },
 {
  "id": "slides-lec23-implicit-declaration",
  "kind": "slides",
  "title": "Κλήση πριν από τον ορισμό",
  "source": {
   "title": "Διάλεξη 23, διαφάνειες 19-21",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec23.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   23,
   3
  ],
  "topics": [
   "functions",
   "compilation"
  ],
  "difficulty": 1,
  "type": "debug",
  "label": "Α23.1",
  "path": "questions/slides/slides-lec23-implicit-declaration.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec23-implicit-declaration.html",
  "statement": "Το παρακάτω πρόγραμμα `prototype.c` μεταγλωττίζεται με μήνυμα\n`implicit declaration of function ‘print_err’`. Γιατί; Διορθώστε το χωρίς να\nμετακινήσετε τον ορισμό της `print_err`.\n\n```c\n#include <stdio.h>\n\nint main() {\n  print_err(\"hello\");\n  return 0;\n}\nint print_err(char * msg) {\n  return fprintf(stderr, \"%s\\n\", msg);\n}\n```\n\n```text\n$ gcc -o prototype prototype.c\nprototype.c: In function ‘main’:\nprototype.c:4:3: warning: implicit declaration of function ‘print_err’\n[-Wimplicit-function-declaration]\n    4 |   print_err(\"hello\");\n      |   ^~~~~~~~~\n```\n\nΜετά τη διόρθωση:\n\n```text\n$ gcc -o prototype prototype.c\n$ ./prototype\nhello\n```",
  "hint": "Ο μεταγλωττιστής της C διαβάζει το αρχείο μία φορά, από πάνω προς τα κάτω. Τι\nχρειάζεται να ξέρει για την `print_err` όταν φτάσει στη γραμμή 4, και πώς του το\nλέτε χωρίς να γράψετε το σώμα της;"
 },
 {
  "id": "slides-lec23-organize-40kloc",
  "kind": "slides",
  "title": "Ένα σύστημα 40.000 γραμμών",
  "source": {
   "title": "Διαλέξεις 23–24, διαφάνειες 11 και 14 (διάλεξη 24: διαφάνειες 12 και 15)",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec23.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   23,
   24
  ],
  "topics": [
   "code-organization",
   "good-practice"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α23.2",
  "path": "questions/slides/slides-lec23-organize-40kloc.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec23-organize-40kloc.html",
  "statement": "Υλοποιούμε ένα καινούριο σύστημα και περιμένουμε να έχει ~40 χιλιάδες γραμμές\nκώδικα. Τι κάνουμε; Ποιος είναι ο καλύτερος τρόπος να οργανώσουμε τον κώδικά μας;\n\nΣυγκρίνετε δύο λύσεις: (1) όλος ο κώδικας σε ένα αρχείο C και (2) οργάνωση του\nκώδικα σε πολλά αρχεία, και δώστε θετικά και αρνητικά για την καθεμία.",
  "hint": "Σκεφτείτε τι συμβαίνει όταν ψάχνετε κάτι σε ένα αρχείο με δεκάδες χιλιάδες γραμμές\nκαι όταν αλλάζετε μία μόνο γραμμή και πρέπει να ξαναμεταγλωττίσετε. Για τη δεύτερη\nλύση, θυμηθείτε την ιδέα της αφαίρεσης: τι ρόλο παίζουν τα αρχεία `.c` και τα `.h`;"
 },
 {
  "id": "slides-lec24-binary-literal",
  "kind": "slides",
  "title": "Ο τυχερός αριθμός σε δυαδικό",
  "source": {
   "title": "Διάλεξη 24: Προχωρημένα Θέματα, διαφάνεια 32",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/lec24.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   24,
   2
  ],
  "topics": [
   "integer-representation",
   "types"
  ],
  "difficulty": 1,
  "type": "trace",
  "label": "Α24.1",
  "path": "questions/slides/slides-lec24-binary-literal.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lec24-binary-literal.html",
  "statement": "Τι θα τυπώσει αυτό το πρόγραμμα;\n\n```c\n#include <stdio.h>\n\nint main() {\n  int i = 0b101010;\n  printf(\"My lucky number is: %d\\n\", i);\n  return 0;\n}\n```",
  "hint": "Το πρόθεμα `0b` (C2X) σημαίνει ότι τα ψηφία που ακολουθούν είναι δυαδικά. Γράψτε\nτη θέση κάθε bit από δεξιά (θέση 0) και αθροίστε τις δυνάμεις του 2 για όσα bit είναι 1."
 },
 {
  "id": "slides-lecmake-build-pipeline",
  "kind": "slides",
  "title": "Τα στάδια του C build process",
  "source": {
   "title": "How to Make? (προσκεκλημένη διάλεξη), διαφάνεια 5",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/make.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   26,
   0
  ],
  "topics": [
   "compilation"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α26.1",
  "path": "questions/slides/slides-lecmake-build-pipeline.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lecmake-build-pipeline.html",
  "statement": "«Say 'Aye' if you know what this is!» Η διαφάνεια δείχνει το παρακάτω διάγραμμα:\n\n```text\nTranslation Unit (.c) -> Preprocessor (cpp) -> Preprocessed Translation Unit (.c)\n  -> Compiler (gcc) -> Object File (.o) -> Linker (ld) -> Executable\n                        Object File (.o) -----^\n                   Dynamic Library (.so) -----^\n```\n\nΕξηγήστε τι κάνει το καθένα από τα τρία στάδια (preprocessor, compiler, linker) και τι\nπαράγει. Γιατί ο linker δέχεται και άλλα object files και δυναμικές βιβλιοθήκες;",
  "hint": "Σκεφτείτε τι απογίνονται οι οδηγίες `#include` και `#define`, σε ποιο στάδιο ο κώδικας\nγίνεται γλώσσα μηχανής, και πού βρίσκεται η υλοποίηση της `printf` που καλεί το\nπρόγραμμά σας."
 },
 {
  "id": "slides-lecmake-forgot-recompile",
  "kind": "slides",
  "title": "Script ή recompile με το χέρι;",
  "source": {
   "title": "How to Make? (προσκεκλημένη διάλεξη), διαφάνειες 17-21",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/make.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   26
  ],
  "topics": [
   "make",
   "compilation"
  ],
  "difficulty": 1,
  "type": "short-answer",
  "label": "Α26.2",
  "path": "questions/slides/slides-lecmake-forgot-recompile.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lecmake-forgot-recompile.html",
  "statement": "Χτίζουμε ένα project με ένα bash script, `build.sh`, που τρέχει ένα `gcc -c` για\nκάθε αρχείο `.c` και ένα `gcc -o` για τη σύνδεση.\n\n1. Κάθε φορά που τρέχουμε το script, ξαναμεταγλωττίζεται όλο το πρόγραμμα από την\n   αρχή, ανεξάρτητα από το αν άλλαξε κάποιο αρχείο. «Και;» Σκεφτείτε την GNU C Library:\n   1.524.568 γραμμές κώδικα σε πάνω από 14.000 αρχεία. Αν θέλαμε απλά να βάλουμε\n   σχόλια σε ένα αρχείο, ακούγεται για καλή χρήση του χρόνου μας;\n2. Εναλλακτική: «Θα κάνω recompile με το χέρι τα αρχεία που αλλάζω, θα κάνω link με\n   ένα bash script, κι αν θέλω να κάνω compile όλο το project, θα έχω ένα άλλο script\n   για αυτό.» Κι αν ξεχάσεις να κάνεις κάτι recompile; Τι θα δείτε όταν τρέξετε το\n   πρόγραμμα;\n3. Τι πληροφορία χρειάζεται ένα εργαλείο για να αποφασίσει μόνο του ποια αρχεία να\n   ξαναμεταγλωττίσει;",
  "hint": "Για το 2, θυμηθείτε την ιστορία του Steve Johnson που αναφέρει ο Stuart Feldman. Για\nτο 3, σκεφτείτε τι εξαρτάται από τι (ένα `.o` από ποια `.c` και `.h`) και πώς\nκαταλαβαίνουμε ότι ένα αρχείο άλλαξε μετά από ένα άλλο."
 },
 {
  "id": "slides-lecmake-per-file-flags",
  "kind": "slides",
  "title": "Διαφορετικά flags ανά αρχείο",
  "source": {
   "title": "How to Make? (προσκεκλημένη διάλεξη), διαφάνειες 10-14",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/make.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   26
  ],
  "topics": [
   "compilation",
   "code-organization"
  ],
  "difficulty": 1,
  "type": "tooling",
  "label": "Α26.3",
  "path": "questions/slides/slides-lecmake-per-file-flags.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lecmake-per-file-flags.html",
  "statement": "Ένα project έχει δύο αρχεία, το `main.c` και το `primes.c`, και μέχρι τώρα χτίζεται\nμε\n\n```text\n$ gcc -Wall -Wextra -Werror -std=c99 -pedantic -o main main.c primes.c\n```\n\nΘέλω το `primes.c` translation unit να μην έχει το standard enforcement\n(`-std=c99`), επειδή θέλω να χρησιμοποιήσω την `reallocarray`, που είναι\nnon-standard. Το `main.c` πρέπει να κρατήσει όλα τα flags. Πώς θα το κάνω αυτό;\nΓράψτε τις εντολές.",
  "hint": "Με μία εντολή `gcc` όλα τα αρχεία παίρνουν τα ίδια flags. Σπάστε το compilation σε\nβήματα: θυμηθείτε ποιο flag του `gcc` σταματά πριν από τη σύνδεση και τι αρχείο\nπαράγει."
 },
 {
  "id": "slides-lecmake-short-makefile",
  "kind": "slides",
  "title": "Ένα Makefile 2-3 γραμμών",
  "source": {
   "title": "How to Make? (προσκεκλημένη διάλεξη), διαφάνειες 31-39",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/make.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   26
  ],
  "topics": [
   "make"
  ],
  "difficulty": 2,
  "type": "tooling",
  "label": "Α26.5",
  "path": "questions/slides/slides-lecmake-short-makefile.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lecmake-short-makefile.html",
  "statement": "Το παρακάτω Makefile χτίζει το project `main` (αρχεία `main.c`, `primes.c`,\n`primes.h`):\n\n```make\nmain: main.o primes.o\n\tgcc -o main main.o primes.o\n\nmain.o: main.c primes.h\n\tgcc -Wall -Wextra -Werror -pedantic -std=c99 -c main.c\n\nprimes.o: primes.c primes.h\n\tgcc -Wall -Wextra -Werror -pedantic -c primes.c\n```\n\nΛειτουργεί; Ναι. Είναι καλό; Όχι.\n\n1. Ξαναγράψτε το με macros (`CC`, `CFLAGS`), ώστε κάποιος που χρησιμοποιεί `clang` να\n   αλλάζει μία μόνο γραμμή.\n2. Χρησιμοποιήστε automatic variables και ένα wildcard rule, ώστε να μην\n   επαναλαμβάνονται τα rules των object files.\n3. Χρησιμοποιώντας τα built-in rules του Make, κάντε το Makefile 2-3 γραμμές.\n\nΕλέγξτε ότι μετά από `touch main.c` το `make` ξαναφτιάχνει μόνο το `main.o` και\nτο `main`.",
  "hint": "Τα `$@`, `$^` και `$<` είναι το target, όλα τα prerequisites και το πρώτο\nprerequisite. Τα built-in rules χρησιμοποιούν τα macros `CC` και `CFLAGS`· ένα rule\nχωρίς recipe απλώς προσθέτει prerequisites. Το `-std=c99` μόνο για το `main.o`\nχρειάζεται ανάθεση μέσα σε rule."
 },
 {
  "id": "slides-lecmake-sqrt-errors",
  "kind": "slides",
  "title": "Compiler error ή linking error; (math.h και libm.so)",
  "source": {
   "title": "How to Make? (προσκεκλημένη διάλεξη), διαφάνειες 6-8",
   "url": "https://github.com/progintro/progintro.github.io/releases/download/2025/make.pdf",
   "years": [
    2025
   ]
  },
  "chapters": [
   26,
   3
  ],
  "topics": [
   "compilation"
  ],
  "difficulty": 1,
  "type": "debug",
  "label": "Α26.4",
  "path": "questions/slides/slides-lecmake-sqrt-errors.md",
  "url": "https://progintro.github.io/study/questions/slides/slides-lecmake-sqrt-errors.html",
  "statement": "Το πρόγραμμα:\n\n```c\n#include <stdio.h>\n// does-not-compile\nint main(void) {\n    printf(\"%.2f\\n\", sqrt(3));\n    return 0;\n}\n```\n\n```text\n$ gcc -o main main.c\nmain.c: In function 'main':\nmain.c:4:20: error: implicit declaration of function 'sqrt'\n[-Wimplicit-function-declaration]\nmain.c:2:1: note: include '<math.h>' or provide a declaration of 'sqrt'\n```\n\n1. Τι έγινε εδώ; Τι είδους error είναι αυτό;\n2. Προσθέτουμε `#include <math.h>` και ξανατρέχουμε:\n\n   ```text\n   $ gcc -o main main.c\n   /usr/bin/ld: /tmp/ccaw9D8e.o: in function `main':\n   main.c:(.text+0x1f): undefined reference to `sqrt'\n   collect2: error: ld returned 1 exit status\n   ```\n\n   Τι είδους error είναι αυτό τώρα; Παρατηρήστε ότι, σε αντίθεση με τον compiler, το\n   μήνυμα δεν είναι και πολύ βοηθητικό. Έχει κανείς ιδέα γιατί;\n3. Πώς το διορθώνουμε ώστε το `./main` να τυπώσει `1.73`;",
  "hint": "Ποιο πρόγραμμα βγάζει κάθε μήνυμα (δείτε τη λέξη `ld`); Ένα αρχείο `.h` δίνει\nδηλώσεις, όχι υλοποιήσεις: σκεφτείτε σε ποιο object file ή βιβλιοθήκη βρίσκεται η\n`sqrt` και πώς το λέτε στον linker."
 }
]