Solutions#
Lunar lander control#
Solution to Activity 2
- air_conditioner = 1;
- if (...) else ...
- a > b
- 5
- success = a > b;
Solution to Activity 3
#include <stdio.h>
int Control(int altitude) {
  int thruster = 0;
  //// BEGIN SOLUTION
  if (altitude > 100)
    thruster = 0;
  else if (altitude > 0)
    thruster = 1;
  else
    thruster = 0;
  //// END SOLUTION
  return thruster;
}
void Test(int altitude) {
  int thruster = Control(altitude);
  int behaviorCorrect = (altitude > 100 && thruster == 0) ||
                        (altitude <= 100 && altitude > 0 && thruster == 1) ||
                        (altitude <= 0 && thruster == 0);
  char *behaviorCorrectIcon = behaviorCorrect ? "โ
" : "โ";
  printf("For altitude %3d, your thruster is %d |%s|\n", altitude, thruster,
         behaviorCorrectIcon);
}
int main(void) {
  Test(150);
  Test(100);
  Test(50);
  Test(0);
  Test(-1);
}
Conveyor belt capacity check#
Solution to Activity 8
#include <stdio.h>
const double packageWeightPerMotor = 5.6;
int main(void) {
  printf("How many motors are carrying the packages? ");
  int motorCount;
  scanf("%d", &motorCount);
  printf("How many kg of packages do we expect? ");
  double packageWeight;
  scanf("%lf", &packageWeight);
  puts(packageWeight / motorCount <= packageWeightPerMotor
           ? "Yes! The conveyor belt can carry the packages."
           : "No. The conveyor belt cannot carry the packages.");
}
Spare parts inventory assistant#
Solution to Activity 13
- int array[];
- int array;
- char[] choices = {"black bird", "great tit", "falcon"};
- char names[] = {"ird", "grea", "con"};
- int part_ids[]= {3093, -49318, 3092.812};- You will get a warning about implicit type conversion of 3092.812. 
- string names[] = [];- 1. We need curly brackets 2. `string` does not exist 
- double intensity[X][Y][Z];
Solution to Activity 20
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Configurable data
#define LINE_SIZE 100
const char *PARTS[] = {"hydraulic pump", "PLC module", "servo motor"};
const char ASSISTANT_GREETING[] =
    "Hej. Welcome to the spare parts inventory!\n";
const char ASSISTANT_QUESTION[] = "Which part do you need? ";
const char ASSISTANT_REPLY_POSITIVE[] = "I have got %s here for you ๐. Bye!\n";
const char ASSISTANT_REPLY_NEGATIVE[] =
    "I am afraid we don't have any %s in the inventory ๐\n";
const char *USER_QUESTIONS[] = {
    "Do you actually have any parts?",
    "Is there anything in stock at all?",
};
const char ASSISTANT_REPLY_NUMBER_OF_PARTS[] = "We have %lu part(s)!\n";
// Program logic
bool user_asked_a_question = false;
int main(void) {
  printf(ASSISTANT_GREETING);
  while (true) { // Program exits through return
    printf("%s ", ASSISTANT_QUESTION);
    char line[LINE_SIZE];
    fgets(line, sizeof line, stdin);
    line[strcspn(line, "\n")] = '\0'; // replace newline
    // Part check
    for (size_t i = 0; i < _Countof PARTS; ++i) {
      if (strcmp(PARTS[i], line) == 0) {
        printf(ASSISTANT_REPLY_POSITIVE, line);
        return EXIT_SUCCESS;
      }
    }
    // Other question check
    for (size_t i = 0; i < _Countof(USER_QUESTIONS); ++i) {
      if (strcmp(USER_QUESTIONS[i], line) == 0) {
        user_asked_a_question = true;
        printf(ASSISTANT_REPLY_NUMBER_OF_PARTS, _Countof(PARTS));
        for (size_t i = 0; i < _Countof(PARTS); ++i)
          puts(PARTS[i]);
        break;
      }
    }
    // If it was not a user question, then it must have been a part
    if (!user_asked_a_question) {
      printf(ASSISTANT_REPLY_NEGATIVE, line);
      user_asked_a_question = false;
    }
  }
}
Rock paper scissors lizard Spock#
Solution to Activity 29 (RPS resolution logic)
#include <stdio.h>
enum { ROCK, PAPER, SCISSORS, SHAPE_COUNT } p1, p2;
const char *SHAPE_STRINGS[] = {"๐ชจ", "๏ธ๐๏ธ", "โ๏ธ"};
int main() {
  for (size_t p1 = 0; p1 < SHAPE_COUNT; ++p1) {
    for (size_t p2 = 0; p2 < SHAPE_COUNT; ++p2) {
      printf("If p1: %s  and p2: %s  => ", SHAPE_STRINGS[p1],
             SHAPE_STRINGS[p2]);
      //// BEGIN SOLUTION
      if (p1 == ROCK && p2 == PAPER)
        puts("p1 looses.");
      else if (p1 == ROCK && p2 == SCISSORS)
        puts("p1 wins.");
      else if (p1 == PAPER && p2 == ROCK)
        puts("p1 wins.");
      else if (p1 == PAPER && p2 == SCISSORS)
        puts("p1 looses.");
      else if (p1 == SCISSORS && p2 == ROCK)
        puts("p1 looses.");
      else if (p1 == SCISSORS && p2 == PAPER)
        puts("p1 wins.");
      else
        puts("Tie.");
      //// END SOLUTION
    }
    puts("");
  }
}
#include <stdio.h>
enum { ROCK, PAPER, SCISSORS, SHAPE_COUNT } p1, p2;
const char *SHAPE_STRINGS[] = {"๐ชจ", "๏ธ๐๏ธ", "โ๏ธ"};
int main() {
  for (size_t p1 = 0; p1 < SHAPE_COUNT; ++p1) {
    for (size_t p2 = 0; p2 < SHAPE_COUNT; ++p2) {
      printf("If p1: %s  and p2: %s  => ", SHAPE_STRINGS[p1],
             SHAPE_STRINGS[p2]);
      //// BEGIN SOLUTION
      switch (p1) {
      case ROCK:
        switch (p2) {
        case PAPER:
          puts("p1 looses.");
          break;
        case SCISSORS:
          puts("p1 wins.");
          break;
        default:
          puts("Tie.");
        }
        break;
      case PAPER:
        switch (p2) {
        case ROCK:
          puts("p1 wins.");
          break;
        case SCISSORS:
          puts("p1 looses.");
          break;
        default:
          puts("Tie.");
        }
        break;
      case SCISSORS:
        switch (p2) {
        case ROCK:
          puts("p1 looses.");
          break;
        case PAPER:
          puts("p1 wins.");
          break;
        default:
          puts("Tie.");
        }
        break;
      }
      //// END SOLUTION
    }
    puts("");
  }
}
#include <stdio.h>
enum { ROCK, PAPER, SCISSORS, SHAPE_COUNT } p1, p2;
const char *SHAPE_STRINGS[] = {"๐ชจ", "๏ธ๐๏ธ", "โ๏ธ"};
int main() {
  for (size_t p1 = 0; p1 < SHAPE_COUNT; ++p1) {
    for (size_t p2 = 0; p2 < SHAPE_COUNT; ++p2) {
      printf("If p1: %s  and p2: %s  => ", SHAPE_STRINGS[p1],
             SHAPE_STRINGS[p2]);
      //// BEGIN SOLUTION
      const enum {
        W,
        L,
        T
      } resolution_table[][T + 1] = {
          {T, L, W},
          {W, T, L},
          {L, W, T},
      }; // (p1, p2, resolution)
      switch (resolution_table[p1][p2]) {
      case T:
        puts("Tie.");
        break;
      case W:
        puts("p1 wins.");
        break;
      case L:
        puts("p1 loses.");
      }
      //// END SOLUTION
    }
    puts("");
  }
}
Solution to Activity 21 (Flowchart v1 โ overview)
        flowchart TD
_s(start) -->b[Welcome user and show menu]
b --> c{menu}
c -->|game| s["print *Starting Game*"]
c -->|exit| f[Say goodbye]--> _e
c -->|else| t[Error message]--> c
s --> g[Game] --> _e
_e(end)
    Solution to Activity 30 (RPSSL resolution logic using difference between shapes)
#include <stdio.h>
enum { SPOCK, SCISSORS, PAPER, ROCK, LIZARD, SHAPE_COUNT } player1, player2;
const char *SHAPE_STRINGS[] = {"๐", "โ๏ธ", "๏ธ๐๏ธ", "๐ชจ", "๐ฆ"};
int main() {
  for (size_t player1 = SPOCK; player1 < SHAPE_COUNT; ++player1) {
    for (size_t player2 = SPOCK; player2 < SHAPE_COUNT; ++player2) {
      printf("If player1: %s  and player2: %s  => ", SHAPE_STRINGS[player1],
             SHAPE_STRINGS[player2]);
      //// BEGIN SOLUTION
      switch (player2 - player1) {
      case 0:
        puts("Tie.");
        break;
      case -4:
      case -2:
      case 1:
      case 3:
        puts("Player1 wins.");
        break;
      default:
        puts("Player1 looses.");
      }
      //// END SOLUTION
    }
    puts("");
  }
}
Refinement for the Game process:
        flowchart TD
  _s(start)--> w{winning score reached?}
  w -->|no| m[ask the player to act]
  m --> s[save players input]
  s --> m2[generate a random shape]
  m2 --> s2[compare shapes]
  s2 --> c{outcome}
  c -->|Human won| c1[++human_score] --> p
  c -->|Agent won| c2[++agent_score] --> p
  c -->|"else (tie)"| p
  p[announce scores] --> w
  w -->|yes| p2[Announce the winner] --> _e
  _e(end)
    #include <stdio.h>
#include <stdlib.h>
#include <time.h>
const unsigned WINNING_SCORE = 5;
// String constants
const char WELCOME[] = R"(
Welcome to ๐ชจ  โ๏ธ  ๐๏ธ  ๐  ๐ฆ !
(s) Single player
(e) Exit
)";
const char SELECT_MENU_ITEM[] = "Select an item: ";
const char SELECT_SHAPE[] = R"(
Select a shape:
0๐ชจ  || 1๐ฆ  || 2โ๏ธ  || 3๐๏ธ  || 4๐ : )";
const char AGENT_PLAYED[] = "Agent: %d\n";
const char STARTING_GAME[] = "Starting game ๐";
const char EXITING_GAME[] = "Bye ๐";
const char GAME_SHAPE_KEY_DOES_NOT_EXIST[] =
    "โ Shape key %c does not exist. Try again.\n";
const char HUMAN_REPR[] = "๐ซ Human";
const char AGENT_REPR[] = "๐ค Agent";
const char SCORE_STATUS[] = "๐ซ:๐ค  %d:%d\n";
const char MENU_USE_RIGHT_KEYS[] = "Use the keys`s`, or `e`.";
// Datatypes
typedef enum { ROCK, LIZARD, SCISSORS, PAPER, SPOCK, SHAPE_COUNT } shape_t;
int main() {
  srand(time(NULL)); // Use another random sequence every time
  printf(WELCOME);
  int input_char; // for getchar()
  // Menu
  bool invalid_menu_key_used;
  do {
    invalid_menu_key_used = false;
    printf(SELECT_MENU_ITEM);
    switch (input_char = getchar()) {
    case 's':
      puts(STARTING_GAME);
      break;
    case 'e':
      puts(EXITING_GAME);
      return EXIT_SUCCESS;
    default:
      invalid_menu_key_used = true;
      puts(MENU_USE_RIGHT_KEYS);
    }
    while (getchar() != '\n')
      ;
  } while (invalid_menu_key_used);
  // Game
  unsigned human_score = 0, agent_score = 0;
  while (human_score < WINNING_SCORE && agent_score < WINNING_SCORE) {
    shape_t human_shape, agent_shape;
    printf(SELECT_SHAPE);
    auto input_char = getc(stdin);
    human_shape = input_char - '0';
    // Go back to 0, so the chars '0', '1', '2' ... correspond to 0, 1, 2 ...
    while (getchar() != '\n')
      ; // Flush \n and other characters
    if (human_shape >= SHAPE_COUNT) {
      printf(GAME_SHAPE_KEY_DOES_NOT_EXIST, input_char);
      continue;
    }
    agent_shape = rand() % SHAPE_COUNT;
    printf(AGENT_PLAYED, agent_shape);
    // Resolution
    auto difference = (agent_shape - human_shape + SHAPE_COUNT) % SHAPE_COUNT;
    if (difference == 0) {
      ;
    } else if (difference <= 2)
      ++human_score;
    else
      ++agent_score;
    printf(SCORE_STATUS, human_score, agent_score);
  }
  // Announce the winner
  printf("%s won!\n", human_score > agent_score ? HUMAN_REPR : AGENT_REPR);
}
Knightโs tour#
Solution to Activity 35 (A shorter tour on a 4x4 board)
Here is a solution with 15 squares generated by ChatGPT after thinking ~40s. It is not a closed-loop, so it applies only to starts from corners.
10  7 12  3
13  4  9  6
 8 11  2 15
 1 14  5  .
Maze#
Solution to Activity 42 (Meaning of pointer operators)
- a == 42
- *a == 42
- &a == 42
- &*b == 42
- *&b == 42
Output of the last two expressions and repeated dereferencing:
#include <stdio.h>
int main() {
  int b = 42;
  int *a = &b;
  // printf("&*b: %d\n", &*b); โ Does not work, `b` must be a pointer
  printf("*&b: %d\n", *&b);
  // For the curious:
  // printf("&&b: %p\n", &(&b));โ Does not work, `&` expects a variable (an
  // lvalue)
  // printf("&&b: %p\n", &&b);โ Does not work, `**` gets the address of a
  // label, `b` must be a label
}
*&b: 42
Solution to Activity 41 (Pointing to a collage vs recreating it)
Advantages of 1
- Only one poster exists 
- No synchronization needed 
- You save space 
- Each friend must be cautious when they work with the poster. They will be stressed about breaking something. 
Disadvantages of 1
- Your friends must come to your room 
- You have to recreate the poster for each friend 
Solution to Activity 44 (Pointer arithmetic with char vs int)
If we increment a pointer, then it points to the start of the next data. The start of the next data is dependent on the size, in our case sizeof(int).
So pointer arithmetic scales automatically based on the size of the type.
Solution to Activity 45 (Calculating pointer + n)
address + index * size_of(datatype)
Warning
Following code scales twice: we have to convert the pointer to a number to make it work:
double arr[] = {100.1, 2, 3.43};
double *target_addr(double *base_addr, size_t index) {
  return base_addr + index * sizeof(double);
}
Solution to Activity 46 (Pass by address vs value using scalar values and array)
#include <stdio.h>
void set_to_42(int *n) {
  //// BEGIN SOLUTION
  *n = 42;
  //// END SOLUTION
}
void set_to_58(int n) {
  //// BEGIN SOLUTION
  n = 58;
  //// END SOLUTION
}
void set_first_element_to_58(int *arr) { // Same as int arr[]
  //// BEGIN SOLUTION
  arr[0] = 58;
  //// END SOLUTION
}
int main() {
  int n;
  int arr[10];
  // Use the first function
  //// BEGIN SOLUTION
  set_to_42(&n);
  //// END SOLUTION
  printf("n: %d\n", n);
  // Use the second function
  //// BEGIN SOLUTION
  set_to_58(n);
  //// END SOLUTION
  printf("n: %d\n", n);
  // Use the third function
  //// BEGIN SOLUTION
  set_first_element_to_58(arr);
  //// END SOLUTION
  printf("arr[0]: %d\n", arr[0]);
}
