Problem A: Neural Network components
Solution description:-
This problem shows a simple neural network (multi-layer perceptron) that predicts whether a
restaurant customer was satisfied.
1. The red circles represent the input neurons, which are the features "Duration stayed" and
"Tip received".
2. The arrows are weights that determine how much influence each input has on the next
layer.
3. The orange circle is the bias unit, which helps shift the activation function for better
fitting.
4. Each hidden node (Box A) performs a weighted sum (Σ) of its inputs plus bias, then
applies an activation function (f).
5. The green circle is the output neuron, which gives the predicted output (y^) (Box B).
Problem B: Cake Calculator
Description:-
This problem asks us to calculate how many cakes a baker can make with a given supply of flour
and sugar, and how much of each ingredient will remain afterwards.
Each cake requires:
100 units of flour
50 units of sugar
Reasoning:-
1. Initialize ingredients and counters
Set the required amounts: flour_needed = 100 and sugar_needed = 50.
Start with cake_count = 0.
2. Use a loop to simulate baking cakes
As long as there is enough flour and sugar for at least one cake, subtract the recipe
requirements from the available flour and sugar.
Each time we subtract, increment cake_count by 1.
3. Stopping condition
If at any point there isn’t enough flour or sugar left for another cake, the loop stops.
4. Remaining ingredients
After the loop ends, the leftover values of flour and sugar are stored as flour_left and
sugar_left.
5. Return values
Finally, return a list with three values:
The total number of cakes baked.
The leftover flour.
The leftover sugar.
Example
If we call cake_calculator(500, 200):
First cake: 500–100 = 400 flour, 200–50 = 150 sugar
Second cake: 400–100 = 300 flour, 150–50 = 100 sugar
Third cake: 300–100 = 200 flour, 100–50 = 50 sugar
Fourth cake: 200–100 = 100 flour, 50–50 = 0 sugar
At this point, no more sugar remains → loop stops.
So the result is: [4, 100, 0].
Input: (500, 200) → [4, 100, 0]
Input: (250, 500) → [2, 50, 400]
Input: (90, 200) → [0, 90, 200]
Python code:
def cake_calculator(flour, sugar):
flour_needed = 100 # recipe requires 100 units of flour
sugar_needed = 50 # recipe requires 50 units of sugar
cake_count = 0 # start with 0 cakes
while True:
if flour < flour_needed or sugar < sugar_needed:
break # stop if not enough ingredients for a cake
flour -= flour_needed
sugar -= sugar_needed
cake_count += 1
# remaining ingredients
flour_left = flour
sugar_left = sugar
return [cake_count, flour_left, sugar_left]
# Example calls
print(cake_calculator(500, 200))
print(cake_calculator(250, 500))
print(cake_calculator(90, 200))
Output:
[4, 100, 0]
[2, 50, 400]
[0, 90, 200]
Problem C : The School Messaging App
Question 1)
In fixed-length encoding, 12 symbols require 4 bits each, so even rare characters use the
same cost.
Variable-length encoding assigns shorter codes to frequent symbols (e.g., A, p=0.20) and
longer codes to rare ones (e.g., K, p=0.02). This lowers the average bits per character,
so more text fits in the data limit.
Example: If A is encoded with 3 bits instead of 4, and it appears 20% of the time, the
total space saved is significant.
Question 2)
Entropy measures the average information content per symbol. It is calculated as:
H=−i=1∑12pilog2(pi)
H = – (p₁ × log₂ (p₁) + p₂ × log₂ (p₂) + … + p₁₂ × log₂ (p₁₂))
Sample terms:
For A (p = 0.20): −0.20×log₂(0.20)≈0.464
For K (p = 0.02): −0.02l×log₂(0.02)≈0.113
(Other characters are computed the same way.)
Total: H≈3.324 bits/character
The entropy is ≈ 3.324 bits/character, which is the theoretical lower bound for any code.
Question 3)
The average code length is calculated by multiplying each symbol’s probability by its
code length and summing over all symbols:
L=i=1∑12pi×code length(i)
Calculation (from the Fano table): L≈3.98 bits/character
Efficiency is given by:
η=H/L= 3.3243.98 ≈83.5%
Problem D: Word Search Puzzle
Reasoning and Description:-
The task is to generate a word search puzzle (10×10 grid) from a given list of words. The words
must appear as continuous sequences in the grid. They may be placed horizontally, vertically, or
diagonally, in any direction, but they must all fit inside the 10×10 grid.
Steps in Solution:
1. Initialize a 10×10 grid
Create a 2D list filled with placeholder characters (e.g., ".") to represent empty spaces.
2. Place each word
For each word in the input list:
o Randomly choose a direction: horizontal, vertical, or diagonal.
o Randomly choose a starting position in the grid where the word can fit.
o Check if the cells are free (either empty or already containing the correct
matching letter).
o Place the word in that position.
3. Fill empty cells
After placing all words, fill the remaining empty cells with random uppercase letters (A–
Z) to complete the puzzle.
4. Return the grid
Finally, return the 2D list of characters representing the crossword puzzle.
Python code:
import random
import string
def create_crossword(words):
size = 10
grid = [["." for _ in range(size)] for _ in range(size)]
# Possible directions: (row change, col change)
directions = [(0, 1), (1, 0), (1, 1), (-1, 1)]
def can_place(word, row, col, dr, dc):
for i in range(len(word)):
r, c = row + dr * i, col + dc * i
if not (0 <= r < size and 0 <= c < size):
return False
if grid[r][c] != "." and grid[r][c] != word[i]:
return False
return True
def place_word(word):
placed = False
attempts = 0
while not placed and attempts < 100:
dr, dc = [Link](directions)
row, col = [Link](0, size - 1), [Link](0, size - 1)
if can_place(word, row, col, dr, dc):
for i in range(len(word)):
grid[row + dr * i][col + dc * i] = word[i]
placed = True
attempts += 1
# Place all words
for word in words:
place_word([Link]())
# Fill remaining cells with random letters
for r in range(size):
for c in range(size):
if grid[r][c] == ".":
grid[r][c] = [Link](string.ascii_uppercase)
return grid
# Example usage
words = ["learning", "science", "fun"]
puzzle = create_crossword(words)
# Display the puzzle
for row in puzzle:
print(" ".join(row))
Output:
CMMCFTURFV
VLNUMPWUOE
OEWRRETTEZ
UACLFZCCWR
IRTKZTNGPV
QNIKCETIBA
OISUINRFUN
KNLCOKIELW
WGSHNSYMDF
FGTYKCACKW
Problem E: Functional Completeness of NAND
Reasoning and Description:
The NAND gate is defined as x↑y = ¬ (x∧y). It outputs 0 only when both inputs are 1,
and 1 otherwise. To prove that NAND is functionally complete, we must show that the
basic Boolean operators NOT, AND, and OR can be expressed using only NAND:
1) NOT:
¬x=x↑x
2) AND:
x∧y= (x↑y) ↑ (x↑y)
3) OR(using De Morgan’s law):
x∨y= (x↑x) ↑ (y↑y)
Since any Boolean function can be expressed using combinations of AND, OR, and NOT,
and each of these can be built using only NAND, it follows that the NAND gate is
functionally complete