InterviewPitch
Shell interview questions

Shell Interview Questions with Answers

Most Asked Shell Interview Questions for Software Engineer Roles

100+ QuestionsDetailed AnswersCode ExamplesUpdated for 2026

Introduction

This page provides a complete collection of Shell Interview Questions and Answers designed for frontend developers, full-stack developers, React developers, Angular developers, and software engineers preparing for technical interviews. Shell is a strongly typed programming language developed by Microsoft that extends JavaScript by adding static typing, interfaces, advanced type checking, and modern development features. It helps developers build scalable and maintainable applications. This interview guide covers beginner, intermediate, and advanced Shell concepts including types, interfaces, classes, generics, decorators, utility types, modules, Shell with React, Angular, Node.js, and real-world coding interview scenarios.

Why Shell?

  • Strong static typing – catches errors at compile time, reducing runtime bugs
  • Excellent tooling and IDE support – autocompletion, navigation, and refactoring
  • Superset of JavaScript – works seamlessly with all existing JavaScript libraries
  • Used by major frameworks like React, Angular, and Vue – essential for large-scale apps
  • Enables scalable and maintainable enterprise-grade applications
  • Growing community, continuous improvements, and high demand in the job market

Most Asked Shell Interview Questions

Beginner
1. What is Shell Scripting?

Shell scripting is the process of writing programs in a shell (command-line interpreter) to automate tasks, manage systems, and perform various operations.

  • Automation: Automate repetitive tasks
  • System administration: Manage and configure systems
  • Batch processing: Process files and data
  • Integration: Connect different tools
  • Portability: Works across Unix-like systems
bash
#!/bin/bash
# Hello World in Shell
echo "Hello, World!"
Beginner
2. How to declare variables in Shell?

Variables in shell are declared using the variable=value syntax. No spaces around the equals sign.

  • Declaration: name="value"
  • Access: $name or {name}
  • Local variables: local var="value"
  • Environment variables: export VAR="value"
  • Read-only: readonly VAR="value"
bash
#!/bin/bash
# Variables in Shell
x=10          # Integer
y=3.14        # Float (as string)
name="Shell"  # String
is_active=true # Boolean (as string)

echo $x
echo $y
echo $name
echo $is_active
Beginner
3. What are the data types in Shell?

Shell is dynamically typed. Everything is treated as a string, but arithmetic operations can be performed on numeric strings.

  • Strings: "Hello"
  • Integers: 10
  • Arrays: (1 2 3)
  • Associative arrays: declare -A map
  • Booleans: true, false
bash
#!/bin/bash
# Data Types in Shell
# Shell is dynamically typed - everything is a string

# Integer
a=10

# Float (as string)
d=3.14

# String
f="Hello Shell"

# Boolean (as string)
g=true
h=false

# Array
j=(1 "hello" 3.14)
k=(1 2 3 4 5)

# Associative array (Bash 4+)
declare -A l
l[name]="Shell"
l[version]=5.0

# Null (unset variable)
m=""

echo $a
echo ${k[0]}
Beginner
4. How to define functions in Shell?

Functions in shell are defined using the function_name() { commands; } syntax or function function_name { commands; }.

  • Syntax: my_function() { echo "Hello"; }
  • Parameters: $1, $2
  • Return: return value
  • Local variables: local var="value"
  • Export: export -f function_name
bash
#!/bin/bash
# Functions in Shell
# Function declaration
add() {
    echo $(( $1 + $2 ))
}

# Function with default parameters
greet() {
    local name="${1:-Guest}"
    echo "Hello, $name!"
}

# Function with return value
subtract() {
    echo $(( $1 - $2 ))
}

# Function with variable arguments
sum_all() {
    local sum=0
    for num in "$@"; do
        sum=$((sum + num))
    done
    echo $sum
}

# Function with named arguments (using local variables)
create_person() {
    local name="$1"
    local age="${2:-0}"
    local city="${3:-Unknown}"
    echo "Name: $name, Age: $age, City: $city"
}

# Usage
add 5 3
greet "Alice"
subtract 10 4
sum_all 1 2 3 4 5
create_person "Alice" 25 "NYC"
Beginner
5. What are arrays in Shell?

Arrays in shell are ordered collections that can hold multiple values. They support both indexed and associative arrays.

  • Indexed arrays: arr=(1 2 3)
  • Associative arrays: declare -A arr
  • Access: {arr[0]}
  • Add: arr+=(4)
  • Length: {#arr[@]}
bash
#!/bin/bash
# Arrays in Shell
arr=(1 2 3 4 5)

# Map - transform each element
doubled=()
for i in "${arr[@]}"; do
    doubled+=($((i * 2)))
done
echo "${doubled[@]}"

# Filter - select elements
evens=()
for i in "${arr[@]}"; do
    if [ $((i % 2)) -eq 0 ]; then
        evens+=($i)
    fi
done
echo "${evens[@]}"

# Reduce - aggregate
sum=0
for i in "${arr[@]}"; do
    sum=$((sum + i))
done
echo $sum

# Push and pop
arr+=(6)
echo "${arr[@]}"
unset 'arr[-1]'
echo "${arr[@]}"

# Array operations
a=(1 2 3)
b=(4 5 6)
c=()
for i in "${!a[@]}"; do
    c+=($((a[i] + b[i])))
done
echo "${c[@]}"
Beginner
6. What are associative arrays in Shell?

Associative arrays in shell are key-value pairs (dictionaries) declared with declare -A.

  • Declaration: declare -A map
  • Add: map[key]="value"
  • Access: {map[key]}
  • Keys: {!map[@]}
  • Check: [[ -v map[key] ]]
bash
#!/bin/bash
# Associative Arrays (Dictionaries) in Shell
declare -A person
person[name]="Alice"
person[age]=25
person[city]="NYC"

# Access values
echo "${person[name]}"
echo "${person[age]}"

# Add/update values
person[country]="USA"
person[age]=26

# Get with default
city="${person[city]:-Unknown}"

# Keys and values
echo "${!person[@]}"
echo "${person[@]}"

# Iterate over associative array
for key in "${!person[@]}"; do
    echo "$key => ${person[$key]}"
done

# Delete key
unset 'person[country]'

# Check if key exists
if [[ -v person[name] ]]; then
    echo "Name exists"
fi

# Associative array from arrays
keys=(1 2 3 4 5)
values=(1 4 9 16 25)
declare -A squares
for i in "${!keys[@]}"; do
    squares[${keys[i]}]=${values[i]}
done
Beginner
7. What are tuples in Shell?

Shell doesn't have native tuples, but arrays can be used as tuple-like structures for ordered collections.

  • Arrays as tuples: (1 "hello" 3.14)
  • Access: {tuple[0]}
  • Unpacking: read a b c <<< "$tuple"
  • Return multiple values: Use echo with read
  • Concatenation: t3=("{t1[@]}" "{t2[@]}")
bash
#!/bin/bash
# Arrays as Tuples in Shell
# Create tuple-like array
t=(1 "hello" 3.14 true)

# Access elements
echo "${t[0]}"
echo "${t[1]}"

# Array unpacking
tuple=(10 20 30)
a=${tuple[0]}
b=${tuple[1]}
c=${tuple[2]}
echo "$a, $b, $c"

# Function returning multiple values
divide() {
    local a=$1
    local b=$2
    echo $((a / b))
    echo $((a % b))
}
read quotient remainder < <(divide 10 3)
echo "Quotient: $quotient, Remainder: $remainder"

# Array concatenation
t1=(1 2 3)
t2=(4 5 6)
t3=("${t1[@]}" "${t2[@]}")
echo "${t3[@]}"
Beginner
8. What are control flow statements in Shell?

Shell provides standard control flow statements including conditionals, loops, and case statements.

  • If-else: if [ condition ]; then ... fi
  • For loop: for i in {1..10}; do ... done
  • While loop: while [ condition ]; do ... done
  • Case: case $var in pattern) ...;; esac
  • Break/Continue: break, continue
bash
#!/bin/bash
# Control Flow in Shell
# If-else statement
age=25
if [ $age -lt 18 ]; then
    echo "Minor"
elif [ $age -lt 65 ]; then
    echo "Adult"
else
    echo "Senior"
fi

# Ternary-like (using && and ||)
[ $age -ge 18 ] && status="Adult" || status="Minor"
echo $status

# For loop
for i in {1..5}; do
    echo $i
done

# For loop with array
fruits=("apple" "banana" "orange")
for fruit in "${fruits[@]}"; do
    echo $fruit
done

# While loop
i=1
while [ $i -le 5 ]; do
    echo $i
    i=$((i + 1))
done

# Break and continue
for i in {1..10}; do
    if [ $i -eq 6 ]; then
        break
    fi
    if [ $((i % 2)) -eq 0 ]; then
        continue
    fi
    echo $i
done
Beginner
9. How to generate arrays in Shell?

Arrays in shell can be generated using loops, brace expansion, seq, and various built-in mechanisms.

  • Brace expansion: {1..10}
  • Seq: $(seq 1 10)
  • Loops: for i in {1..10}; do arr+=($i); done
  • Map: Transform with loops
  • Filter: Conditional addition
bash
#!/bin/bash
# Array Generation in Shell
# Using sequence
squares=()
for i in {1..10}; do
    squares+=($((i * i)))
done
echo "${squares[@]}"

# Filter with condition
evens=()
for i in {1..20}; do
    if [ $((i % 2)) -eq 0 ]; then
        evens+=($i)
    fi
done
echo "${evens[@]}"

# Nested loops
pairs=()
for i in {1..3}; do
    for j in {1..3}; do
        pairs+=("$i,$j")
    done
done
echo "${pairs[@]}"

# Conditional array
results=()
for i in {1..10}; do
    if [ $((i % 2)) -eq 0 ]; then
        results+=("even")
    else
        results+=("odd")
    fi
done
echo "${results[@]}"

# Using seq
for i in $(seq 1 10); do
    echo $i
done
Beginner
10. How to work with strings in Shell?

Shell provides various string manipulation operations including concatenation, substitution, and extraction.

  • Concatenation: "$str1 $str2"
  • Length: {#string}
  • Substring: {string:0:5}
  • Replace: {string/old/new}
  • Case conversion: {string^^}, {string,,}
bash
#!/bin/bash
# Strings in Shell
# String creation
str1="Hello"
str2='World'
str3="Multi-line
string"

# String concatenation
greeting="$str1 $str2"
echo "$greeting"

# String interpolation
name="Shell"
version=5.0
echo "Welcome to $name version $version"

# String functions
text="Hello, World!"
echo "${#text}"
echo "${text^^}"
echo "${text,,}"
echo "${text/World/Shell}"

# Substring
echo "${text:0:5}"

# Split and join
IFS=' ' read -ra words <<< "Hello World Shell"
echo "${words[@]}"
joined=$(IFS='-'; echo "${words[*]}")
echo "$joined"

# String comparison
[ "hello" == "hello" ] && echo "Equal"
[ "hello" < "world" ] && echo "Less than"

# String formatting
printf "Value: %.2f
" 3.14159
Beginner
11. What are modules in Shell?

Shell modules are scripts that can be sourced (included) to reuse functions and variables across scripts.

  • Sourcing: source script.sh or . script.sh
  • Functions: Define reusable functions
  • Variables: Define constants
  • Export: export -f function_name
  • Libraries: Organize code into files
bash
#!/bin/bash
# Functions and Scripts as Modules in Shell
# Creating a module (save as math.sh)
# add() { echo $(( $1 + $2 )); }
# subtract() { echo $(( $1 - $2 )); }

# Sourcing a script
# source math.sh
# . math.sh

# Using the module
# add 5 3
# subtract 10 4

# Creating a library
# save as lib.sh
# PI=3.14159
# add() { echo $(( $1 + $2 )); }

# Using library
# source lib.sh
# echo $PI

# Functions with local variables
my_function() {
    local local_var="Local"
    global_var="Global"
}

# Exporting functions
export -f my_function

# Including external files
# source ./config.sh

# Using alias as module
# alias my_alias='echo "Hello"'

# Creating a script module
# #!/bin/bash
# # mymodule.sh
# export MY_VAR="value"
# function my_func() { echo "Hello"; }

# Loading module
# source ./mymodule.sh
# my_func
Beginner
12. What are variables and types in Shell?

Shell variables are dynamically typed. The declare builtin can be used to set variable attributes.

  • Local: local var="value"
  • Global: var="value"
  • Environment: export var="value"
  • Read-only: readonly var="value"
  • Special variables: $0, $@, $#
bash
#!/bin/bash
# Variables and Types in Shell
# Variable declaration
name="Alice"
age=25
city="NYC"

# Local variables
my_function() {
    local local_var="Local"
    global_var="Global"
}

# Environment variables
export ENV_VAR="Environment"

# Read-only variables
readonly CONSTANT=100

# Special variables
echo "Script name: $0"
echo "First argument: $1"
echo "All arguments: $@"
echo "Number of arguments: $#"
echo "Exit code of last command: $?"
echo "Process ID: $$"

# Variable types (using declare)
declare -i integer=42
declare -r readonly_var=100
declare -a array=(1 2 3)
declare -A associative=([key]="value")

# Checking if variable is set
if [ -z "${var+x}" ]; then
    echo "var is unset"
fi

# Default value
name="${name:-Default}"

# Indirect expansion
var=name
echo ${!var}
Intermediate
13. How to check types in Shell?

Shell provides type checking through pattern matching and built-in operators.

  • Integer check: [[ $var =~ ^-?[0-9]+$ ]]
  • Number check: [[ $var =~ ^-?[0-9]*\.?[0-9]+$ ]]
  • Empty check: [[ -z $var ]]
  • Set check: [[ -v var ]]
  • Array check: declare -p var
bash
#!/bin/bash
# Type Checking in Shell
# Check if variable is integer
is_integer() {
    [[ $1 =~ ^-?[0-9]+$ ]]
}

# Check if variable is number
is_number() {
    [[ $1 =~ ^-?[0-9]*\.?[0-9]+$ ]]
}

# Check if variable is string (always true in shell)
is_string() {
    [[ -n $1 ]]
}

# Check if variable is array
is_array() {
    declare -p "$1" 2>/dev/null | grep -q 'declare -a'
}

# Check if variable is associative array
is_associative_array() {
    declare -p "$1" 2>/dev/null | grep -q 'declare -A'
}

# Type checking examples
num=42
if is_integer "$num"; then
    echo "$num is an integer"
fi

float=3.14
if is_number "$float"; then
    echo "$float is a number"
fi

# Type conversion
number="42"
integer=$((number))
string="Hello"

# Checking variable existence
if [ -n "$var" ]; then
    echo "var is set and not empty"
fi

# Type of variable
declare -p var 2>/dev/null
Intermediate
14. How to handle exceptions in Shell?

Shell handles errors using exit codes, trap, and conditional execution.

  • Exit codes: exit 1
  • Check: if [ $? -ne 0 ]; then ...
  • trap: trap 'command' ERR
  • set -e: Exit on error
  • try-catch: { command } || { error_handler; }
bash
#!/bin/bash
# Exception Handling in Shell
# Try-catch using trap
set -e

# Error handling with trap
error_handler() {
    echo "Error occurred on line $1"
    exit 1
}
trap 'error_handler $LINENO' ERR

# Try-catch pattern
{
    # Code that might error
    result=$((10 / 0))
    echo $result
} || {
    echo "Division by zero error"
}

# Specific error handling
{
    arr=(1 2 3)
   echo ${arr[10]}
} || {
    echo "Index out of bounds"
}

# Finally block (using trap)
cleanup() {
    echo "Cleanup performed"
}
trap cleanup EXIT

# Throwing errors
divide() {
    if [ $2 -eq 0 ]; then
        echo "Cannot divide by zero" >&2
        return 1
    fi
    echo $(( $1 / $2 ))
}

# Using error
if ! result=$(divide 10 0); then
    echo "Error: Division failed"
fi

# Custom error function
error() {
    echo "ERROR: $1" >&2
    exit 1
}

# Usage
# error "Custom error message"

# Checking command success
if command -v non_existent_command &> /dev/null; then
    echo "Command exists"
else
    echo "Command not found"
fi
Intermediate
15. How to work with files in Shell?

Shell provides various commands for file operations including reading, writing, and manipulation.

  • Read: cat file
  • Write: echo "text" > file
  • Append: echo "text" >> file
  • Line by line: while read -r line; do ... done < file
  • File info: stat file, ls -la
bash
#!/bin/bash
# File I/O in Shell
# Reading files
if [ -f "example.txt" ]; then
    content=$(cat "example.txt")
    echo "$content"
else
    echo "File not found"
fi

# Reading line by line
if [ -f "data.txt" ]; then
    while IFS= read -r line; do
        echo "$line"
    done < "data.txt"
fi

# Writing files
echo "Hello, World!" > output.txt
echo "This is line 2" >> output.txt

# Appending to files
echo "Appended line" >> output.txt

# Reading CSV
while IFS=',' read -r name age city; do
    echo "Name: $name, Age: $age, City: $city"
done < data.csv

# Writing CSV
echo "Name,Age,City" > output.csv
echo "Alice,25,NYC" >> output.csv
echo "Bob,30,LA" >> output.csv

# File operations
for file in *.txt; do
    echo "$file"
    echo "$(stat -c%s "$file")"
done

# Reading with cat
cat file.txt

# Using heredoc
cat << EOF > output.txt
Line 1
Line 2
EOF

# Reading with read
read -p "Enter your name: " name
echo "Hello, $name"
Intermediate
16. How to use packages in Shell?

Shell uses system package managers like apt, yum, brew, and others for installing software packages.

  • apt: sudo apt install package
  • yum: sudo yum install package
  • brew: brew install package
  • Check: dpkg -l | grep package
  • Environment: export PATH=$PATH:/path
bash
#!/bin/bash
# Packages and Package Managers in Shell
# Using apt (Debian/Ubuntu)
# sudo apt update
# sudo apt install package-name

# Using yum (RHEL/CentOS)
# sudo yum install package-name

# Using dnf (Fedora)
# sudo dnf install package-name

# Using brew (macOS)
# brew install package-name

# Using snap
# sudo snap install package-name

# Checking if package is installed
dpkg -l | grep -q package-name
if [ $? -eq 0 ]; then
    echo "Package is installed"
fi

# Using pip for Python packages
# pip install package-name

# Using npm for Node.js packages
# npm install package-name

# Environment variables for packages
export PATH=$PATH:/usr/local/bin

# Loading package module
# module load package-name

# Creating a package script
# #!/bin/bash
# # mypackage.sh
# echo "My Package"

# Making script executable
# chmod +x myscript.sh

# Running script
# ./myscript.sh

# Installing from source
# ./configure
# make
# sudo make install
Intermediate
17. How to create plots in Shell?

Shell can create plots using external tools like gnuplot, python matplotlib, R, or terminal-based utilities.

  • gnuplot: Create plots from data
  • python: Use matplotlib
  • R: Use ggplot2
  • asciiplot: Terminal plots
  • spark: Terminal sparklines
bash
#!/bin/bash
# Plotting in Shell
# Using gnuplot
gnuplot << EOF
set terminal png
set output "plot.png"
set title "Square Function"
set xlabel "x"
set ylabel "y"
plot [1:10] x**2 with lines
EOF

# Using python matplotlib from shell
python3 << EOF
import matplotlib.pyplot as plt
import numpy as np

x = np.arange(1, 10, 0.1)
y = x**2

plt.plot(x, y)
plt.title("Square Function")
plt.xlabel("x")
plt.ylabel("y")
plt.savefig("plot.png")
EOF

# Using R from shell
Rscript -e '
x <- 1:10
y <- x^2
png("plot.png")
plot(x, y, type="l", main="Square Function")
dev.off()
'

# Creating data file for gnuplot
cat << EOF > data.dat
1 1
2 4
3 9
4 16
5 25
EOF

gnuplot << EOF
set terminal png
set output "plot2.png"
plot "data.dat" with linespoints
EOF

# Using asciiplot (terminal plots)
# npm install -g asciiplot
# asciiplot "1 4 9 16 25"

# Using spark (terminal sparklines)
# echo "1 2 3 4 5 6 7 8 9 10" | spark
Intermediate
18. What are data structures in Shell?

Shell provides arrays and associative arrays as primary data structures, with additional structures built using these.

  • Stack: Array with push/pop
  • Queue: Array with enqueue/dequeue
  • Map: Associative arrays
  • Set: Array with unique values
  • Tree: Using filesystem or nested arrays
bash
#!/bin/bash
# Data Structures in Shell
# Array as Stack (LIFO)
stack=()
push() {
    stack+=("$1")
}
pop() {
    local len=${#stack[@]}
    if [ $len -gt 0 ]; then
        local last=$((len - 1))
        echo "${stack[$last]}"
        unset 'stack[$last]'
        stack=("${stack[@]}")
    fi
}

# Array as Queue (FIFO)
queue=()
enqueue() {
    queue+=("$1")
}
dequeue() {
    if [ ${#queue[@]} -gt 0 ]; then
        echo "${queue[0]}"
        queue=("${queue[@]:1}")
    fi
}

# Associative array as Map
declare -A map
map["key"]="value"

# Set using array
set_add() {
    local element=$1
    if [[ ! " ${set[@]} " =~ " $element " ]]; then
        set+=("$element")
    fi
}

# Usage
push 1
push 2
push 3
pop  # returns 3

enqueue 1
enqueue 2
enqueue 3
dequeue  # returns 1

# Environment as data structure
export MY_VAR="value"

# Using temporary files for data structures
temp_file=$(mktemp)
echo "data" > "$temp_file"
rm "$temp_file"
Intermediate
19. How to do statistics in Shell?

Shell can perform statistical operations using bc, awk, sort, and custom functions.

  • Mean: Sum / count
  • Median: Sort and find middle
  • Standard deviation: Custom calculation
  • Correlation: Custom implementation
  • Quantiles: Custom sorting
bash
#!/bin/bash
# Statistics in Shell
# Basic statistics functions
mean() {
    local sum=0
    local count=0
    for num in "$@"; do
        sum=$((sum + num))
        count=$((count + 1))
    done
    echo "scale=2; $sum / $count" | bc
}

median() {
    local arr=("$@")
    local n=${#arr[@]}
    local sorted=($(printf '%s
' "${arr[@]}" | sort -n))
    if [ $((n % 2)) -eq 1 ]; then
        echo "${sorted[$((n/2))]}"
    else
        local left=${sorted[$((n/2 - 1))]}
        local right=${sorted[$((n/2))]}
        echo "scale=2; ($left + $right) / 2" | bc
    fi
}

# Standard deviation
std_dev() {
    local arr=("$@")
    local avg=$(mean "${arr[@]}")
    local sum=0
    for num in "${arr[@]}"; do
        local diff=$(echo "$num - $avg" | bc)
        sum=$(echo "$sum + $diff * $diff" | bc)
    done
    local n=${#arr[@]}
    echo "scale=2; sqrt($sum / $n)" | bc
}

# Correlation (simplified)
correlation() {
    local x=("${!1}")
    local y=("${!2}")
    # Implementation would be more complex
}

# Usage
data=(1 2 3 4 5 6 7 8 9 10)
mean "${data[@]}"
median "${data[@]}"
std_dev "${data[@]}"
Intermediate
20. How to do linear algebra in Shell?

Shell can perform linear algebra operations using arrays and external tools like bc or python.

  • Matrix operations: Using arrays
  • Transpose: Swap indices
  • Multiplication: Dot product
  • Norm: Sum of squares
  • Vector ops: Dot product, norm
bash
#!/bin/bash
# Linear Algebra in Shell
# Matrix operations
declare -A matrix

# Matrix multiplication
mat_mul() {
    local -n A=$1
    local -n B=$2
    local -n R=$3
    local rows=${#A[@]}
    local cols=${#B[0,@]}
    local inner=${#B[@]}
    
    for ((i=0; i<rows; i++)); do
        for ((j=0; j<cols; j++)); do
            sum=0
            for ((k=0; k<inner; k++)); do
                sum=$((sum + A[$i,$k] * B[$k,$j]))
            done
            R[$i,$j]=$sum
        done
    done
}

# Transpose
transpose() {
    local -n matrix=$1
    local -n result=$2
    local rows=${#matrix[@]}
    local cols=${#matrix[0,@]}
    
    for ((i=0; i<rows; i++)); do
        for ((j=0; j<cols; j++)); do
            result[$j,$i]=${matrix[$i,$j]}
        done
    done
}

# Vector operations
dot_product() {
    local -n a=$1
    local -n b=$2
    local sum=0
    for i in "${!a[@]}"; do
        sum=$((sum + a[i] * b[i]))
    done
    echo $sum
}

# Norm
norm() {
    local -n vector=$1
    local sum=0
    for val in "${vector[@]}"; do
        sum=$((sum + val * val))
    done
    echo "scale=2; sqrt($sum)" | bc
}

# Usage
# mat_mul A B result
Intermediate
21. How to work with dates in Shell?

Shell uses the date command for date manipulation, with formatting and arithmetic capabilities.

  • Current: date
  • Create: date -d "2024-01-01"
  • Arithmetic: date -d "$date + 10 days"
  • Difference: $(( (date2 - date1) / 86400 ))
  • Formatting: date +%Y-%m-%d
bash
#!/bin/bash
# Dates and Time in Shell
# Current date and time
now=$(date)
echo "$now"

# Date creation
date1="2024-01-01"
date2="2024-01-01 12:00:00"
echo "$date1"
echo "$date2"

# Date arithmetic
date1=$(date -d "$date1 + 10 days" +%Y-%m-%d)
echo "$date1"
date1=$(date -d "$date1 + 2 months" +%Y-%m-%d)
echo "$date1"

# Date difference
diff=$(( ($(date -d "$date2" +%s) - $(date -d "$date1" +%s)) / 86400 ))
echo "$diff days"

# Formatting dates
date=$(date -d "2024-01-01" +%Y-%m-%d)
echo "$date"

# Date functions
echo $(date +%Y)
echo $(date +%m)
echo $(date +%d)
echo $(date +%A)

# Date range
start="2024-01-01"
end="2024-01-10"
current="$start"
while [[ $(date -d "$current" +%s) -le $(date -d "$end" +%s) ]]; do
    echo "$current"
    current=$(date -d "$current + 1 day" +%Y-%m-%d)
done

# Timestamps
timestamp=$(date +%s)
echo "$timestamp"
date=$(date -d "@$timestamp")
echo "$date"

# Timezone handling
TZ="America/New_York" date
Intermediate
22. How to use regular expressions in Shell?

Shell supports regex through tools like grep, sed, awk, and Bash's =~ operator.

  • grep: grep "pattern" file
  • sed: sed 's/pattern/replacement/g'
  • awk: awk '/pattern/ {print}'
  • Bash: [[ $text =~ pattern ]]
  • Capture groups: {BASH_REMATCH[1]}
bash
#!/bin/bash
# Regular Expressions in Shell
# Match
text="hello world"
if [[ $text =~ hello ]]; then
    echo "Match found"
fi

# Find all (using grep)
text2="hello world hello again"
echo "$text2" | grep -o "hello"

# Regex with capture groups (using sed)
text3="Date: 2024-01-01"
if [[ $text3 =~ ([0-9]{4})-([0-9]{2})-([0-9]{2}) ]]; then
    echo "Year: ${BASH_REMATCH[1]}"
    echo "Month: ${BASH_REMATCH[2]}"
    echo "Day: ${BASH_REMATCH[3]}"
fi

# Replace with regex (using sed)
replaced=$(echo "Hello 123 World" | sed 's/[0-9]+/NUM/g')
echo "$replaced"

# Case insensitive (using grep)
echo "$text3" | grep -i "hello"

# Split with regex (using awk)
parts=($(echo "Hello World Shell" | awk '{split($0,a,"[ ,]+"); print a[1], a[2], a[3]}'))
echo "${parts[@]}"

# Using grep
if echo "abc123def" | grep -q "[0-9]"; then
    echo "Contains numbers"
fi

# Using awk for regex
echo "1 2 3 4 5" | awk '/[0-9]/ {print $1}'

# Using sed for replacement
echo "Hello World" | sed 's/World/Shell/g'

# Pattern matching in Bash
if [[ "hello" == h* ]]; then
    echo "Starts with h"
fi
Advanced
23. How to do parallel computing in Shell?

Shell supports parallel computing through background processes, xargs, GNU parallel, and job control.

  • Background: command &
  • wait: wait $pid
  • xargs: xargs -P4
  • GNU parallel: parallel -j4
  • Subshells: ( command ) &
bash
#!/bin/bash
# Parallel Computing in Shell
# Using background processes
parallel_task() {
    sleep 2
    echo "Task completed"
}

# Run in background
parallel_task &
parallel_task &
wait
echo "All tasks completed"

# Using xargs for parallel processing
echo {1..10} | xargs -n1 -P4 -I{} echo "Processing {}"

# Using GNU parallel
# parallel -j4 "echo Processing {}" ::: {1..10}

# Using subshells for parallel tasks
(
    sleep 2
    echo "Task 1 done"
) &
(
    sleep 1
    echo "Task 2 done"
) &
wait

# Using make for parallel execution
# make -j4

# Using for loops with &
for i in {1..10}; do
    (
        sleep 1
        echo "Processing $i"
    ) &
done
wait

# Using while loop with background
while read -r line; do
    (
        echo "Processing $line"
    ) &
done < input.txt
wait

# Using named pipes (FIFO)
mkfifo pipe
(
    echo "Data" > pipe
) &
read data < pipe
rm pipe

# Using parallel for file processing
find . -name "*.txt" -print0 | xargs -0 -P4 -I{} echo "Processing {}"
Advanced
24. What is metaprogramming in Shell?

Shell supports metaprogramming through eval, dynamic variable names, and code generation.

  • eval: eval "echo Hello"
  • Dynamic variables: {!var_name}
  • Dynamic functions: eval "func() { echo Hi; }"
  • Code generation: Using here-documents
  • Source: source generated.sh
bash
#!/bin/bash
# Metaprogramming in Shell
# Using eval for dynamic code execution
code='echo "Hello World"'
eval "$code"

# Dynamic function calls
function add() {
    echo $(( $1 + $2 ))
}
func_name="add"
$func_name 5 3

# Dynamic variable names
var_name="x"
eval "$var_name=10"
echo $x

# Using indirect expansion
var="name"
name="Alice"
echo "${!var}"

# Creating functions dynamically
eval 'my_function() { echo "Dynamic function"; }'
my_function

# Using here-documents for code generation
cat << 'EOF' > generated.sh
#!/bin/bash
echo "Generated script"
EOF
chmod +x generated.sh
./generated.sh

# Using source for dynamic loading
source ./config.sh

# Using declare for dynamic variables
declare -a dynamic_array
for i in {1..5}; do
    dynamic_array+=("$i")
done

# Using alias for dynamic commands
alias my_cmd='echo "Hello"'
my_cmd

# Using trap for dynamic behavior
trap 'echo "Interrupted"' INT

# Using ${!var} for indirect references
a="Hello"
b="a"
echo "${!b}"
Advanced
25. How to interface with C in Shell?

Shell can interface with C programs by compiling and running them, or by using system calls.

  • Compile: gcc -o program program.c
  • Run: ./program
  • Pass arguments: ./program arg1 arg2
  • Check exit code: $?
  • Environment: export VAR="value"
bash
#!/bin/bash
# Interoperability with C in Shell
# Compiling C program
# gcc -o program program.c

# Running C program
./program

# Passing arguments to C program
./program arg1 arg2

# Using system calls from C
# system("ls -la");

# Using popen to read C program output
./program | while read -r line; do
    echo "$line"
done

# Using C program with pipes
./program | grep "pattern"

# Creating a C shared library
# gcc -shared -o libmylib.so mylib.c

# Calling C library from shell (using dlopen)
# Not directly supported

# Using C program exit codes
./program
if [ $? -eq 0 ]; then
    echo "Success"
else
    echo "Failed"
fi

# Passing environment variables to C program
export MY_VAR="value"
./program

# Using C program with file I/O
./program input.txt output.txt

# Compiling and running in one command
gcc -o program program.c && ./program

# Using C program with signals
./program &
kill -SIGUSR1 $!
Advanced
26. How to optimize performance in Shell?

Shell performance can be optimized through built-in commands, avoiding subshells, and using efficient loops.

  • Built-ins: Use shell built-ins vs external
  • Avoid subshells: Use pushd vs (cd ...)
  • Arrays: Use arrays for collections
  • Process substitution: <(command)
  • Brace expansion: {1..1000}
bash
#!/bin/bash
# Performance Optimization in Shell
# Performance tips

# 1. Use built-in commands instead of external
# Instead of: ls | wc -l
# Use: echo "${#files[@]}"

# 2. Use bash built-ins
# Instead of: echo "Hello" | grep "H"
# Use: [[ "Hello" =~ H ]]

# 3. Avoid subshells when possible
# Instead of: (cd /tmp && ls)
# Use: pushd /tmp && ls && popd

# 4. Use arrays instead of strings
files=()
for file in *; do
    files+=("$file")
done

# 5. Use process substitution
while read -r line; do
    echo "$line"
done < <(find . -name "*.txt")

# 6. Use brace expansion
for i in {1..1000}; do
    echo $i
done

# 7. Use arithmetic evaluation
sum=0
for i in {1..1000}; do
    ((sum += i))
done

# 8. Use nullglob
shopt -s nullglob
for file in *.txt; do
    echo "$file"
done

# 9. Use bash's read with -r
while IFS= read -r line; do
    echo "$line"
done < file.txt

# 10. Use exec for redirecting output
exec > output.log 2>&1

# 11. Use ulimit for resource limits
ulimit -n 4096

# 12. Profile with time
time ./script.sh

# 13. Use set -o pipefail for pipelines
set -o pipefail

# 14. Use compgen for completion
compgen -c | head -10

# 15. Use shopt for shell options
shopt -s extglob
Advanced
27. How to do networking in Shell?

Shell provides networking through curl, wget, nc, and other network tools.

  • curl: curl -s URL
  • wget: wget -qO- URL
  • netcat: nc -zv host port
  • SSH: ssh user@host command
  • SCP: scp local.txt user@host:/remote/
bash
#!/bin/bash
# Networking in Shell
# HTTP GET request using curl
fetch_data() {
    curl -s "$1"
}

# Example
# data=$(fetch_data "https://api.github.com")
# echo "$data"

# HTTP POST request
post_data() {
    curl -s -X POST -H "Content-Type: application/json" -d "$2" "$1"
}

# Using wget
wget -O output.html https://example.com

# Using nc (netcat) for TCP
nc -zv example.com 80
if [ $? -eq 0 ]; then
    echo "Port 80 is open"
fi

# TCP client
send_tcp() {
    local host=$1
    local port=$2
    local message=$3
    echo "$message" | nc "$host" "$port"
}

# TCP server (using nc)
# nc -l -p 8080 -e /bin/bash

# DNS resolution
host example.com
nslookup example.com
dig example.com

# Ping
ping -c 4 example.com

# Traceroute
traceroute example.com

# Using ssh for remote commands
# ssh user@host "command"

# Using scp for file transfer
# scp local.txt user@host:/remote/

# Using rsync for synchronization
# rsync -av source/ destination/

# Using nmap for port scanning
# nmap -p 1-1000 example.com

# Using telnet for testing
# telnet example.com 80
Advanced
28. How to work with JSON in Shell?

Shell works with JSON using jq for parsing, manipulation, and generation of JSON data.

  • Parse: echo '{"name":"Alice"}' | jq '.name'
  • Pretty print: echo '{"name":"Alice"}' | jq '.'
  • Generate: jq -n '{name: "Bob"}'
  • Arrays: echo '[1,2,3]' | jq '.[]'
  • Nested: echo '{"user":{"name":"Alice"}}' | jq '.user.name'
bash
#!/bin/bash
# Working with JSON in Shell
# Using jq
data='{"name":"Alice","age":25,"city":"NYC","hobbies":["reading","coding"]}'

# Parse JSON
echo "$data" | jq '.name'
echo "$data" | jq '.age'
echo "$data" | jq '.hobbies[0]'

# Pretty print
echo "$data" | jq '.'

# Create JSON
jq -n '{name: "Bob", age: 30, city: "LA"}'

# Array to JSON
echo '[1,2,3,4,5]' | jq '.'

# Nested JSON
nested='{"user":{"id":1,"profile":{"name":"Alice","email":"alice@example.com"}}}'
echo "$nested" | jq '.user.profile.name'

# Read JSON from file
# cat data.json | jq '.'

# Write JSON to file
echo '{"name":"Alice","age":25}' | jq '.' > output.json

# Using jq with variables
name="Bob"
age=30
echo "{}" | jq --arg n "$name" --arg a "$age" '.name=$n | .age=$a'

# JSON arrays
echo '["apple","banana","orange"]' | jq '.[]'

# JSON transformation
echo '{"name":"Alice","age":25}' | jq '{fullname: .name, years: .age}'

# Error handling
if echo "$data" | jq empty 2>/dev/null; then
    echo "Valid JSON"
else
    echo "Invalid JSON"
fi
Advanced
29. How to test code in Shell?

Shell testing can be done with custom assert functions, BATS (Bash Automated Testing System), or shunit2.

  • Custom asserts: assert() { [ "$1" = "$2" ]; }
  • BATS: @test "name" { [ ... ]; }
  • shunit2: test_addition() { assertEquals ...; }
  • Test suites: Group tests
  • Coverage: bashcov
bash
#!/bin/bash
# Testing in Shell
# Using bash unit test frameworks

# Simple assert function
assert() {
    if [ "$1" = "$2" ]; then
        echo "PASS: $3"
        return 0
    else
        echo "FAIL: $3 - Expected: $1, Got: $2"
        return 1
    fi
}

# Test function
test_addition() {
    result=$(add 2 2)
    assert 4 "$result" "2 + 2 = 4"
}

# Test with floating point
test_float() {
    local result=$(echo "0.1 + 0.2" | bc)
    local expected="0.3"
    if (( $(echo "$result == $expected" | bc -l) )); then
        echo "PASS: Float test"
    else
        echo "FAIL: Float test - Expected: $expected, Got: $result"
    fi
}

# Test with exit code
test_exit_code() {
    ./script.sh
    if [ $? -eq 0 ]; then
        echo "PASS: Exit code test"
    else
        echo "FAIL: Exit code test - Expected: 0, Got: $?"
    fi
}

# Test suite
run_tests() {
    test_addition
    test_float
    test_exit_code
}

# Using BATS (Bash Automated Testing System)
# https://github.com/bats-core/bats-core

# BATS test example
# @test "addition works" {
#   result=$(add 2 2)
#   [ "$result" -eq 4 ]
# }

# Using shunit2
# source shunit2
# test_addition() {
#   assertEquals "2 + 2 = 4" 4 "$(add 2 2)"
# }
# shunit2

# Running tests
# run_tests
# bats test.bats
# ./test.sh
Advanced
30. How to debug in Shell?

Shell provides debugging through trace mode (set -x), verbose mode, and various debugging tools.

  • set -x: Trace execution
  • set -v: Verbose mode
  • echo: Print debug messages
  • trap: Error handling
  • shellcheck: Static analysis
bash
#!/bin/bash
# Debugging in Shell
# Using echo for debugging
debug_function() {
    echo "Entering function with x=$1" >&2
    result=$(( $1 * 2 ))
    echo "Result = $result" >&2
    echo $result
}
debug_function 5

# Using set -x for trace mode
set -x
# Code here will be traced
set +x

# Using set -v for verbose mode
set -v
# Code here will be displayed
set +v

# Using PS4 for custom trace output
export PS4='+ $BASH_SOURCE:$LINENO: '
set -x

# Using trap for error handling
trap 'echo "Error on line $LINENO"' ERR

# Using logger for system logging
logger "Debug message"
logger -t myscript "Debug message with tag"

# Using tee for output capture
echo "Hello" | tee -a debug.log

# Using exec for output redirection
exec 2> debug.log

# Using bashdb for debugging
# bashdb script.sh

# Using shellcheck for static analysis
# shellcheck script.sh

# Using set -e to exit on error
set -e

# Using set -u for undefined variables
set -u

# Using set -o pipefail for pipe errors
set -o pipefail

# Using bash -n for syntax checking
# bash -n script.sh

# Using bash -v for verbose execution
# bash -v script.sh

# Using xtrace with xargs
# bash -x script.sh

# Using debug trap
trap 'echo "Line $LINENO: $BASH_COMMAND"' DEBUG
Advanced
31. What are abstract types in Shell?

Shell doesn't have formal abstract types, but functions and case statements can simulate abstract behaviors.

  • Functions: Define interfaces
  • Case statements: Polymorphic dispatch
  • Arrays: Store behaviors
  • Type checking: declare -f
  • Inheritance: Function composition
bash
#!/bin/bash
# Abstract Types and Interfaces in Shell
# Using functions as abstract methods
# Define abstract class pattern
animal() {
    local action=$1
    shift
    case $action in
        make_sound) echo "Animal sound";;
        *) echo "Unknown action";;
    esac
}

# Concrete implementations
dog() {
    local action=$1
    shift
    case $action in
        make_sound) echo "Woof!";;
        *) animal "$action" "$@";;
    esac
}

cat() {
    local action=$1
    shift
    case $action in
        make_sound) echo "Meow!";;
        *) animal "$action" "$@";;
    esac
}

# Interface-like using functions
sound_maker() {
    make_sound "$@"
}

# Usage
dog make_sound
cat make_sound

# Using type checking
is_animal() {
    declare -f "$1" > /dev/null
}

# Using inheritance simulation
sparrow() {
    local action=$1
    shift
    case $action in
        make_sound) echo "Chirp!";;
        *) animal "$action" "$@";;
    esac
}

# Checking object type
if is_animal dog; then
    echo "Dog is an animal"
fi

# Using arrays for polymorphism
animals=(dog cat sparrow)
for animal in "${animals[@]}"; do
    $animal make_sound
done
Advanced
32. What are generic types in Shell?

Shell doesn't have formal generic types, but generic-like behavior can be simulated with arrays and functions.

  • Generic collections: Use arrays
  • Generic functions: Accept arrays as arguments
  • Map: Apply function to each element
  • Filter: Select by predicate
  • Reduce: Aggregate values
bash
#!/bin/bash
# Generic Types in Shell
# Using arrays for generic collections
declare -a list

# Generic list functions
list_add() {
    local -n arr=$1
    arr+=("$2")
}

list_get() {
    local -n arr=$1
    echo "${arr[$2]}"
}

list_length() {
    local -n arr=$1
    echo "${#arr[@]}"
}

# Generic map
map() {
    local -n arr=$1
    local func=$2
    local result=()
    for item in "${arr[@]}"; do
        result+=($($func "$item"))
    done
    echo "${result[@]}"
}

# Generic filter
filter() {
    local -n arr=$1
    local pred=$2
    local result=()
    for item in "${arr[@]}"; do
        if $pred "$item"; then
            result+=("$item")
        fi
    done
    echo "${result[@]}"
}

# Generic reduce
reduce() {
    local -n arr=$1
    local func=$2
    local acc=$3
    for item in "${arr[@]}"; do
        acc=$($func "$acc" "$item")
    done
    echo "$acc"
}

# Usage
numbers=(1 2 3 4 5)
list_add numbers 6
list_get numbers 0
list_length numbers

# Generic functions
double() { echo $(( $1 * 2 )); }
is_even() { [ $(( $1 % 2 )) -eq 0 ]; }

doubled=$(map numbers double)
evens=$(filter numbers is_even)
sum=$(reduce numbers add 0)
Advanced
33. What are traits in Shell?

Traits in shell can be simulated using functions and composition patterns.

  • Functions as traits: Define reusable behaviors
  • Composition: Combine multiple traits
  • Mixins: Add behavior to objects
  • Method override: Redefine functions
  • Validation: Trait with validation
bash
#!/bin/bash
# Traits and Composition in Shell
# Using functions as traits
Logger() {
    log() {
        echo "[LOG] $1"
    }
    error() {
        echo "[ERROR] $1" >&2
    }
}

# Trait with properties
User() {
    local name=""
    local age=0
    set_name() { name=$1; }
    get_name() { echo "$name"; }
    set_age() { age=$1; }
    get_age() { echo "$age"; }
}

# Composition
UserWithLogger() {
    # Compose User and Logger
    User
    Logger
    
    # Override methods if needed
    get_info() {
        echo "Name: $(get_name), Age: $(get_age)"
    }
}

# Usage
user_with_logger=UserWithLogger
$user_with_logger set_name "Alice"
$user_with_logger set_age 25
$user_with_logger get_info
$user_with_logger log "User created"

# Using mixins with arrays
mixins=()
add_mixin() {
    mixins+=("$1")
}

apply_mixins() {
  for mixin in "${mixins[@]}"; do
        $mixin
    done
}

# Trait for validation
Validator() {
    validate_name() {
        [[ -n $1 ]] && return 0 || return 1
    }
    validate_age() {
        [[ $1 -gt 0 ]] && return 0 || return 1
    }
}

# Composition with validation
UserWithValidation() {
    User
    Validator
    set_name() {
        if validate_name "$1"; then
            name=$1
        else
            echo "Invalid name" >&2
        fi
    }
}
Advanced
34. What are generators in Shell?

Generators in shell can be implemented using functions with state, or using FIFOs and process substitution.

  • Stateful functions: Track state in variables
  • FIFOs: Named pipes for streaming
  • Process substitution: <(command)
  • Background jobs: Coroutine-like behavior
  • Lazy evaluation: Using temporary files
bash
#!/bin/bash
# Generators and Coroutines in Shell
# Generator using functions with state
counter_generator() {
    local count=0
    next() {
        echo $((++count))
    }
}

# Using generator
counter=counter_generator
$counter next
$counter next
$counter next

# Fibonacci generator
fibonacci_generator() {
    local a=0
    local b=1
    next() {
        local c=$a
        a=$b
        b=$((c + b))
        echo $c
    }
}

fib=fibonacci_generator
for i in {1..10}; do
    $fib next
done

# Coroutine using named pipes
coroutine() {
    local pipe="/tmp/coro_$$"
    mkfifo "$pipe"
    (
        echo "Coroutine started"
        sleep 2
        echo "Coroutine finished"
    ) > "$pipe" &
    cat "$pipe"
    rm "$pipe"
}

# Using process substitution for coroutines
coproc my_coro {
    while read -r cmd; do
        case $cmd in
            start) echo "Starting";;
            stop) echo "Stopping"; break;;
            *) echo "Unknown: $cmd";;
        esac
    done
}

# Lazy evaluation using temporary files
lazy_eval() {
    local tmp=$(mktemp)
    (
        echo "Computing..."
        sleep 2
        echo "42" > "$tmp"
    ) &
    cat "$tmp"
    rm "$tmp"
}

# Using background jobs as coroutines
job() {
    local name=$1
    for i in {1..5}; do
        echo "$name: $i"
        sleep 1
    done
}

job "A" &
job "B" &
wait
Advanced
35. What are advanced array operations in Shell?

Shell provides basic array operations, and advanced operations can be implemented using loops and custom functions.

  • Matrix ops: Nested arrays
  • Element-wise: Loops
  • Transpose: Swap indices
  • Multiplication: Dot products
  • Norm/Trace: Sum calculations
bash
#!/bin/bash
# Advanced Array Operations
# Array initialization
declare -A matrix
for ((i=0; i<3; i++)); do
    for ((j=0; j<3; j++)); do
        matrix[$i,$j]=$((i*3+j+1))
    done
done

# Reshaping (flatten)
flatten() {
    local -n arr=$1
    for key in "${!arr[@]}"; do
        echo "${arr[$key]}"
    done
}

# Transpose
transpose() {
    local -n A=$1
    local -n B=$2
    for ((i=0; i<3; i++)); do
        for ((j=0; j<3; j++)); do
            B[$j,$i]=${A[$i,$j]}
        done
    done
}

# Element-wise operations
declare -A A
declare -A B
declare -A C
for ((i=0; i<3; i++)); do
    for ((j=0; j<3; j++)); do
        A[$i,$j]=$((i*3+j+1))
        B[$i,$j]=$((A[$i,$j] + 1))
        C[$i,$j]=$((A[$i,$j] * 2))
    done
done

# Matrix multiplication
mat_mul() {
    local -n A=$1
    local -n B=$2
    local -n R=$3
    for ((i=0; i<3; i++)); do
        for ((j=0; j<3; j++)); do
            sum=0
            for ((k=0; k<3; k++)); do
                sum=$((sum + A[$i,$k] * B[$k,$j]))
            done
            R[$i,$j]=$sum
        done
    done
}

# Element-wise multiplication
elementwise_mul() {
    local -n A=$1
    local -n B=$2
    local -n R=$3
    for ((i=0; i<3; i++)); do
        for ((j=0; j<3; j++)); do
            R[$i,$j]=$((A[$i,$j] * B[$i,$j]))
        done
    done
}

# Matrix norm (Frobenius)
norm() {
    local -n A=$1
    local sum=0
    for ((i=0; i<3; i++)); do
        for ((j=0; j<3; j++)); do
            sum=$((sum + A[$i,$j] * A[$i,$j]))
        done
    done
    echo "scale=2; sqrt($sum)" | bc
}

# Trace
trace() {
    local -n A=$1
    local sum=0
    for ((i=0; i<3; i++)); do
        sum=$((sum + A[$i,$i]))
    done
    echo $sum
}

# Diagonal
diag() {
    local -n A=$1
    for ((i=0; i<3; i++)); do
        echo "${A[$i,$i]}"
    done
}
Advanced
36. How to handle missing data in Shell?

Shell handles missing data using empty strings, {var:-default}, and existence checks.

  • Empty strings: Represent null
  • Default values: {var:-default}
  • Existence check: [[ -v var ]]
  • Remove: Filter out empties
  • Replace: {var:-default}
bash
#!/bin/bash
# Handling Missing Data (Null handling)
# Creating arrays with missing values
data=("1" "2" "" "4" "5" "" "7")

# Check for missing values
has_missing() {
    for item in "${@}"; do
        if [ -z "$item" ]; then
            return 0
        fi
    done
    return 1
}

# Remove missing values
remove_missing() {
    local result=()
    for item in "${@}"; do
        if [ -n "$item" ]; then
            result+=("$item")
        fi
    done
    echo "${result[@]}"
}

# Replace missing values
replace_missing() {
    local default=$1
    shift
    local result=()
    for item in "${@}"; do
        if [ -n "$item" ]; then
            result+=("$item")
        else
            result+=("$default")
        fi
    done
    echo "${result[@]}"
}

# Operations with missing values
x=("1" "2" "" "4")
y=("5" "6" "" "8")
z=()
for i in "${!x[@]}"; do
    if [ -n "${x[$i]}" ] && [ -n "${y[$i]}" ]; then
        z+=($((x[i] + y[i])))
    else
        z+=("")
    fi
done

# Ignoring missing values
sum_complete=0
for item in "${x[@]}"; do
    if [ -n "$item" ]; then
        sum_complete=$((sum_complete + item))
    fi
done

# Using default values
value="${data[10]:-default}"

# Checking for unset variables
if [ -z "${var+x}" ]; then
    echo "var is unset"
fi

# Null coalescing (Bash 4+)
var=${var:-default}

# Using parameter expansion
name="${name:-Default}"
Advanced
37. How to do sorting and searching in Shell?

Shell provides sorting through sort and searching through grep, awk, and loops.

  • sort: sort -n
  • Custom sort: sort -k2
  • Search: grep pattern
  • Binary search: Custom implementation
  • Contains: [[ $item =~ pattern ]]
bash
#!/bin/bash
# Sorting and Searching
# Basic sorting
arr=(5 2 8 1 9 3)
sorted=($(printf '%s
' "${arr[@]}" | sort -n))
echo "${sorted[@]}"

# Sorting with custom comparator
arr2=("5 apple" "3 banana" "8 cherry")
sorted2=($(printf '%s
' "${arr2[@]}" | sort -n))
echo "${sorted2[@]}"

# Sorting descending
arr3=(5 2 8 1 9 3)
sorted3=($(printf '%s
' "${arr3[@]}" | sort -nr))
echo "${sorted3[@]}"

# Search functions
arr4=(1 3 5 7 9 11)
greater_than_5=()
for item in "${arr4[@]}"; do
    if [ $item -gt 5 ]; then
        greater_than_5+=("$item")
    fi
done
echo "${greater_than_5[@]}"

# First greater than 5
first_greater=()
for item in "${arr4[@]}"; do
    if [ $item -gt 5 ]; then
        first_greater="$item"
        break
    fi
done
echo "$first_greater"

# Last greater than 5
last_greater=()
for item in "${arr4[@]}"; do
    if [ $item -gt 5 ]; then
        last_greater="$item"
    fi
done
echo "$last_greater"

# Contains
has_seven=0
has_four=0
for item in "${arr4[@]}"; do
    if [ $item -eq 7 ]; then
        has_seven=1
    fi
    if [ $item -eq 4 ]; then
        has_four=1
    fi
done
echo "Has 7: $has_seven, Has 4: $has_four"

# Binary search
binary_search() {
    local arr=("$@")
    local target=${arr[-1]}
    unset 'arr[-1]'
    local left=0
    local right=$((${#arr[@]} - 1))
    
    while [ $left -le $right ]; do
        local mid=$(((left + right) / 2))
        if [ ${arr[$mid]} -eq $target ]; then
            echo $mid
            return
        elif [ ${arr[$mid]} -lt $target ]; then
            left=$((mid + 1))
        else
            right=$((mid - 1))
        fi
    done
    echo -1
}

arr5=(1 2 3 4 5 6 7)
index=$(binary_search "${arr5[@]}" 5)
echo "Found at index: $index"
Advanced
38. What are mathematical operations in Shell?

Shell provides arithmetic operations through $((...)), bc, and awk.

  • Arithmetic: $((1+2))
  • bc: echo "scale=2; 10/3" | bc
  • Trigonometric: bc -l
  • Random: $RANDOM
  • Statistics: Custom functions
bash
#!/bin/bash
# Mathematical Operations
# Basic arithmetic
x=10
y=3
echo "$((x + y))"
echo "$((x - y))"
echo "$((x * y))"
echo "$((x / y))"
echo "$((x % y))"
echo "$((x ** y))"

# Mathematical functions (using bc)
echo "scale=4; s(3.14159/4)" | bc -l
echo "scale=4; c(3.14159/4)" | bc -l
echo "scale=4; e(1)" | bc -l
echo "scale=4; l(e(1))" | bc -l
echo "scale=4; sqrt(9)" | bc -l

# Special functions
echo "abs(-5) = ${abs#-}"
ceil() {
    echo "$1" | awk '{print ($0 == int($0)) ? $0 : int($0) + 1}'
}
floor() {
    echo "$1" | awk '{print ($0 == int($0)) ? $0 : int($0) - 1}'
}
round() {
    echo "$1" | awk '{print int($1 + 0.5)}'
}

# Random numbers
echo $((RANDOM % 10 + 1))
echo $((RANDOM % 100))

# Statistics
data=(1 2 3 4 5 6 7 8 9 10)
sum=0
for i in "${data[@]}"; do
    sum=$((sum + i))
done
echo "sum = $sum"
echo "mean = $(echo "scale=2; $sum / ${#data[@]}" | bc)"

# Min and Max
min=${data[0]}
max=${data[0]}
for i in "${data[@]}"; do
    [ $i -lt $min ] && min=$i
    [ $i -gt $max ] && max=$i
done
echo "min = $min, max = $max"
Advanced
39. How to do data serialization in Shell?

Shell serializes data using text formats like CSV, JSON, YAML, or custom formats with base64 encoding.

  • CSV: Comma-separated values
  • JSON: Using jq
  • YAML: Using yq
  • base64: echo "data" | base64
  • Custom: Key-value pairs
bash
#!/bin/bash
# Data Serialization
# Using echo and cat for simple serialization
data="name:Alice,age:25,city:NYC"
echo "$data" > data.txt
deserialized=$(cat data.txt)
echo "$deserialized"

# Using JSON with jq
echo '{"name":"Alice","age":25}' > data.json
cat data.json | jq '.'

# Using CSV
echo "name,age,city" > data.csv
echo "Alice,25,NYC" >> data.csv
echo "Bob,30,LA" >> data.csv

# Using YAML (requires yq)
# yq eval '.name' data.yaml

# Using XML (requires xmlstarlet)
# xmlstarlet sel -t -v "/root/name" data.xml

# Using base64 encoding
encoded=$(echo "Hello World" | base64)
decoded=$(echo "$encoded" | base64 -d)

# Using tar for archiving
tar -czf archive.tar.gz file1 file2

# Using gzip compression
gzip -c data.txt > data.txt.gz
gunzip -c data.txt.gz > data.txt

# Using serialize/deserialize functions
serialize() {
    echo "$1" | base64
}
deserialize() {
    echo "$1" | base64 -d
}

# Using arrays for serialization
declare -A person
person[name]="Alice"
person[age]=25
person[city]="NYC"

# Serialize associative array
for key in "${!person[@]}"; do
    echo "$key=${person[$key]}"
done > person.dat

# Deserialize
while IFS='=' read -r key value; do
    person2["$key"]="$value"
done < person.dat
Advanced
40. How to interface with external systems in Shell?

Shell interfaces with external systems through database clients, HTTP tools, SSH, and system commands.

  • Database: sqlite3, mysql
  • HTTP: curl, wget
  • SSH: ssh user@host
  • System: command
  • Environment: export
bash
#!/bin/bash
# Interfacing with External Systems
# Database connections (using sqlite3)
sqlite3 database.db "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)"
sqlite3 database.db "INSERT INTO users (name) VALUES ('Alice')"
sqlite3 database.db "SELECT * FROM users"

# Using MySQL
# mysql -u user -p -e "SELECT * FROM users" database

# Using PostgreSQL
# psql -U user -d database -c "SELECT * FROM users"

# Using Redis (with redis-cli)
# redis-cli set key value
# redis-cli get key

# Using HTTP requests
curl -X GET https://api.github.com
curl -X POST -H "Content-Type: application/json" -d '{"name":"Alice"}' https://httpbin.org/post

# Using SSH
# ssh user@host "command"

# Using SCP
# scp local.txt user@host:/remote/

# Using rsync
# rsync -av source/ destination/

# Using system calls
system() {
    command "$@"
}

# Executing shell commands
output=$(ls -la)
echo "$output"

# Using environment variables
export MY_VAR="value"
echo $MY_VAR

# Using temporary files
temp_file=$(mktemp)
echo "data" > "$temp_file"
rm "$temp_file"

# Using named pipes
mkfifo pipe
echo "Hello" > pipe &
cat pipe
rm pipe
Coding Round
41. Reverse a string

Reverse a string by iterating from the end to the beginning.

  • Method: for ((i=${#s}-1; i>=0; i--)); do reversed="${reversed}${s:$i:1}"; done
  • Alternative: rev command
  • Time: O(n)
  • Edge cases: Empty string
bash
#!/bin/bash
# Reverse a string
reverse_string() {
    local s="$1"
    local reversed=""
    for ((i=${#s}-1; i>=0; i--)); do
        reversed="${reversed}${s:$i:1}"
    done
    echo "$reversed"
}

reverse_string_manual() {
    local s="$1"
    local len=${#s}
    local reversed=""
    for ((i=0; i<len; i++)); do
        reversed="${s:$i:1}$reversed"
    done
    echo "$reversed"
}

s="hello"
echo "Original: $s"
echo "Reversed: $(reverse_string "$s")"
echo "Reversed (manual): $(reverse_string_manual "$s")"
Coding Round
42. Check palindrome

Check if a string is a palindrome by comparing it with its reverse.

  • Method: s == $(reverse_string "$s")
  • Case insensitive: {s,,}
  • Ignore spaces: {s// /}
  • Recursive: Compare ends
bash
#!/bin/bash
# Check palindrome
is_palindrome() {
    local s="${1,,}"
    local cleaned="${s// /}"
    local reversed=$(reverse_string "$cleaned")
    [ "$cleaned" = "$reversed" ]
}

is_palindrome_manual() {
    local s="${1,,}"
    local cleaned="${s// /}"
    local len=${#cleaned}
    for ((i=0; i<len/2; i++)); do
        if [ "${cleaned:$i:1}" != "${cleaned:$len-$i-1:1}" ]; then
            return 1
        fi
    done
    return 0
}

strings=("racecar" "hello" "A man a plan a canal Panama" "race a car")
for s in "${strings[@]}"; do
    if is_palindrome "$s"; then
        echo ""$s" is palindrome"
    else
        echo ""$s" is not palindrome"
    fi
done
Coding Round
43. Find max in array

Find the maximum value by iterating through the array.

  • Method: max={arr[0]}; for val in "{arr[@]}"; do [ $val -gt $max ] && max=$val; done
  • Alternative: printf '%s\n' "{arr[@]}" | sort -n | tail -1
  • Empty: Handle empty case
  • Time: O(n)
bash
#!/bin/bash
# Find max in array
find_max() {
    local max=$1
    shift
    for val in "$@"; do
        if [ $val -gt $max ]; then
            max=$val
        fi
    done
    echo $max
}

find_max_manual() {
    local arr=("$@")
    local max=${arr[0]}
    for ((i=1; i<${#arr[@]}; i++)); do
        if [ ${arr[$i]} -gt $max ]; then
            max=${arr[$i]}
        fi
    done
    echo $max
}

arr=(1 5 3 9 2)
echo "Array: ${arr[@]}"
echo "Max: $(find_max "${arr[@]}")"
echo "Max (manual): $(find_max_manual "${arr[@]}")"
Coding Round
44. Remove duplicates

Remove duplicates by tracking seen items and skipping duplicates.

  • Method: printf '%s\n' "{arr[@]}" | sort -u
  • Manual: seen=(); for item in "{arr[@]}"; do ...
  • Preserve order: Manual method
  • Time: O(n²) or O(n log n) with sort
bash
#!/bin/bash
# Remove duplicates
remove_duplicates() {
    local result=()
    local seen=()
    for item in "$@"; do
        local found=0
        for seen_item in "${seen[@]}"; do
            if [ "$seen_item" = "$item" ]; then
                found=1
                break
            fi
        done
        if [ $found -eq 0 ]; then
            seen+=("$item")
            result+=("$item")
        fi
    done
    echo "${result[@]}"
}

remove_duplicates_sort() {
    printf '%s
' "$@" | sort -u
}

arr=("apple" "banana" "apple" "orange" "banana" "grape")
echo "Original: ${arr[@]}"
echo "Without duplicates: $(remove_duplicates "${arr[@]}")"
echo "Without duplicates (sort): $(remove_duplicates_sort "${arr[@]}")"
Coding Round
45. Merge arrays

Merge arrays by concatenating or merging sorted arrays.

  • Concat: result=("{arr1[@]}" "{arr2[@]}")
  • Sorted merge: Compare and add
  • Unique: printf '%s\n' "{arr1[@]}" "{arr2[@]}" | sort -u
  • Time: O(n+m)
bash
#!/bin/bash
# Merge arrays
merge_arrays() {
    echo "${@}"
}

merge_sorted() {
    local arr1=("${!1}")
    local arr2=("${!2}")
    local result=()
    local i=0 j=0
    while [ $i -lt ${#arr1[@]} ] && [ $j -lt ${#arr2[@]} ]; do
        if [ ${arr1[$i]} -le ${arr2[$j]} ]; then
            result+=(${arr1[$i]})
            ((i++))
        else
            result+=(${arr2[$j]})
            ((j++))
        fi
    done
    while [ $i -lt ${#arr1[@]} ]; do
        result+=(${arr1[$i]})
        ((i++))
    done
    while [ $j -lt ${#arr2[@]} ]; do
        result+=(${arr2[$j]})
        ((j++))
    done
    echo "${result[@]}"
}

arr1=(1 2 3)
arr2=(4 5 6)
echo "Merged: $(merge_arrays "${arr1[@]}" "${arr2[@]}")"

sorted1=(1 3 5 7)
sorted2=(2 4 6 8)
echo "Merged sorted: $(merge_sorted sorted1 sorted2)"
Coding Round
46. Convert string to number

Convert a string to a number using arithmetic expansion or bc.

  • Integer: $((var))
  • Float: echo "$var" | bc
  • Safe: ${var//[^0-9.-]/}
  • Error handling: 2>/dev/null
bash
#!/bin/bash
# Convert string to number
string_to_number() {
    echo "$1" | bc 2>/dev/null || echo 0
}

string_to_int() {
    echo "${1//[^0-9-]/}" | bc
}

string_to_float() {
    echo "$1" | bc -l 2>/dev/null || echo 0
}

strings=("42" "3.14" "hello" "123" "45.67")
for s in "${strings[@]}"; do
    echo ""$s" -> int: $(string_to_int "$s"), float: $(string_to_float "$s")"
done
Coding Round
47. Loop through dictionary

Iterate through an associative array using for key in "{!dict[@]}".

  • Keys: {!dict[@]}
  • Values: {dict[$key]}
  • Find key: Check if key exists
  • Return: {dict[$key]:-default}
bash
#!/bin/bash
# Loop through associative array
declare -A data
data[name]="Alice"
data[age]=25
data[city]="NYC"

loop_dict() {
    for key in "${!data[@]}"; do
        echo "$key => ${data[$key]}"
    done
}

find_key() {
    local key=$1
    echo "${data[$key]:-Not found}"
}

echo "Dictionary:"
loop_dict
echo ""
name=$(find_key "name")
echo "Name: $name"
country=$(find_key "country")
echo "Country: $country"
Coding Round
48. Delay function execution

Delay execution using sleep or background processes.

  • Blocking: sleep $seconds; command
  • Async: (sleep $seconds; command) &
  • Callback: Function after delay
  • Timer: Use at or cron
bash
#!/bin/bash
# Delay function execution
delay_seconds() {
    sleep "$1"
    shift
    "$@"
}

delay_async() {
    (
        sleep "$1"
        shift
        "$@"
    ) &
}

delayed_print() {
    echo "Starting delay of $2 seconds"
    delay_seconds "$2" echo "$1"
}

echo "Delayed execution examples:"
delayed_print "After 2 seconds" 2
echo "Main script continues"
Coding Round
49. HTTP GET request

Make HTTP requests using curl or wget.

  • curl: curl -s URL
  • wget: wget -qO- URL
  • Headers: curl -H "Header: value"
  • Error handling: curl -f
bash
#!/bin/bash
# HTTP GET request
fetch_data() {
    curl -s "$1"
}

fetch_data_wget() {
    wget -qO- "$1"
}

post_data() {
    curl -s -X POST -H "Content-Type: application/json" -d "$2" "$1"
}

# Example
# result=$(fetch_data "https://api.github.com")
# echo "$result"

# Using wget
# result=$(fetch_data_wget "https://api.github.com")

# POST example
# result=$(post_data "https://httpbin.org/post" '{"name":"Alice","age":25}')

# Using curl with headers
curl -s -H "User-Agent: Bash" "https://api.github.com"

# Using curl with authentication
# curl -u username:password "https://api.github.com"

# Using curl for file download
# curl -O https://example.com/file.txt

# Using wget for file download
# wget https://example.com/file.txt

# Using httpie
# http GET https://api.github.com

# Error handling
if ! result=$(curl -s -f "https://api.github.com" 2>/dev/null); then
    echo "Error fetching data"
fi
Coding Round
50. Create a promise-like task

Create promise-like behavior using background processes and wait.

  • Promise: (sleep 1; echo "Success") &
  • Wait: wait $pid
  • Check: $? for success/failure
  • Chain: Sequential waits
bash
#!/bin/bash
# Create a promise-like task
create_promise() {
    local should_resolve=$1
    local result=""
    (
        sleep 1
        if [ "$should_resolve" = true ]; then
            echo "Success!"
        else
            echo "Failed!"
            exit 1
        fi
    ) &
    echo $!
}

# Using the promise
pid=$(create_promise true)
wait $pid
if [ $? -eq 0 ]; then
    echo "Promise resolved"
else
    echo "Promise rejected"
fi

# Promise with error handling
pid=$(create_promise false)
wait $pid
if [ $? -eq 0 ]; then
    echo "Promise resolved"
else
    echo "Promise rejected"
fi

# Chain promises
chain_promises() {
    local p1=$1
    local p2=$2
    (
        wait $p1
        if [ $? -eq 0 ]; then
            wait $p2
            if [ $? -eq 0 ]; then
                echo "Both completed"
            else
                echo "Second failed"
            fi
        else
            echo "First failed"
        fi
    ) &
}

# Promise all
promise_all() {
    local pids=("$@")
    for pid in "${pids[@]}"; do
        wait $pid
        if [ $? -ne 0 ]; then
            echo "Failed"
            return 1
        fi
    done
    echo "All succeeded"
}
Coding Round
51. Factorial

Calculate factorial using recursion or iteration.

  • Recursive: factorial() { [ $1 -le 1 ] && echo 1 || echo $(( $1 * $(factorial $(( $1 - 1 )) ) )); }
  • Iterative: for ((i=2; i<=n; i++)); do result=$((result * i)); done
  • Edge cases: 0! = 1
  • Time: O(n)
bash
#!/bin/bash
# Factorial
factorial() {
    if [ $1 -le 1 ]; then
        echo 1
    else
        local n=$1
        local sub=$(factorial $((n - 1)))
        echo $((n * sub))
    fi
}

factorial_iterative() {
    local n=$1
    local result=1
    for ((i=2; i<=n; i++)); do
        result=$((result * i))
    done
    echo $result
}

n=5
echo "Factorial of $n:"
echo "Recursive: $(factorial $n)"
echo "Iterative: $(factorial_iterative $n)"
Coding Round
52. Fibonacci

Calculate Fibonacci numbers using recursion, iteration, or memoization.

  • Recursive: fib() { [ $1 -le 1 ] && echo $1 || echo $(( $(fib $(( $1 - 1 )) ) + $(fib $(( $1 - 2 )) ) )); }
  • Iterative: for ((i=2; i<=n; i++)); do c=$((a+b)); a=$b; b=$c; done
  • Memoized: Use cache file
  • Time: O(n) iterative
bash
#!/bin/bash
# Fibonacci
fibonacci() {
    if [ $1 -le 1 ]; then
        echo $1
    else
        local n=$1
        local a=$(fibonacci $((n - 1)))
        local b=$(fibonacci $((n - 2)))
        echo $((a + b))
    fi
}

fibonacci_iterative() {
    local n=$1
    if [ $n -le 1 ]; then
        echo $n
        return
    fi
    local a=0 b=1
    for ((i=2; i<=n; i++)); do
        local c=$((a + b))
        a=$b
        b=$c
    done
    echo $b
}

fibonacci_memoized() {
    local n=$1
    local cache_file="/tmp/fib_cache_$$"
    if [ -f "$cache_file" ] && grep -q "^$n:" "$cache_file"; then
        grep "^$n:" "$cache_file" | cut -d: -f2
        return
    fi
    local result
    if [ $n -le 1 ]; then
        result=$n
    else
        local a=$(fibonacci_memoized $((n - 1)))
        local b=$(fibonacci_memoized $((n - 2)))
        result=$((a + b))
    fi
    echo "$n:$result" >> "$cache_file"
    echo $result
}
trap 'rm -f /tmp/fib_cache_$$' EXIT

n=10
echo "Fibonacci of $n:"
echo "Recursive: $(fibonacci $n)"
echo "Iterative: $(fibonacci_iterative $n)"
echo "Memoized: $(fibonacci_memoized $n)"
Coding Round
53. FizzBuzz

Print numbers with FizzBuzz logic using conditional statements.

  • If-else: if [ $((i % 15)) -eq 0 ]; then ...
  • Case: case $((i % 15)) in 0) echo "FizzBuzz";; ...
  • Array: Store results
  • Output: echo
bash
#!/bin/bash
# FizzBuzz
fizzbuzz() {
    local n=$1
    for ((i=1; i<=n; i++)); do
        if [ $((i % 15)) -eq 0 ]; then
            echo "FizzBuzz"
        elif [ $((i % 3)) -eq 0 ]; then
            echo "Fizz"
        elif [ $((i % 5)) -eq 0 ]; then
            echo "Buzz"
        else
            echo $i
        fi
    done
}

fizzbuzz_array() {
    local n=$1
    local result=()
    for ((i=1; i<=n; i++)); do
        if [ $((i % 15)) -eq 0 ]; then
            result+=("FizzBuzz")
        elif [ $((i % 3)) -eq 0 ]; then
            result+=("Fizz")
        elif [ $((i % 5)) -eq 0 ]; then
            result+=("Buzz")
        else
            result+=($i)
        fi
    done
    echo "${result[@]}"
}

echo "FizzBuzz for 15:"
fizzbuzz 15

echo "FizzBuzz array:"
fizzbuzz_array 15
Coding Round
54. Find missing number

Find missing number using sum formula or XOR operation.

  • Sum: $((n*(n+1)/2 - sum))
  • XOR: xor_all ^ xor_arr
  • Time: O(n)
  • Edge cases: Empty array
bash
#!/bin/bash
# Find missing number
find_missing() {
    local arr=("$@")
    local n=$((${#arr[@]} + 1))
    local total=$((n * (n + 1) / 2))
    local sum=0
    for num in "${arr[@]}"; do
        sum=$((sum + num))
    done
    echo $((total - sum))
}

find_missing_xor() {
    local arr=("$@")
    local n=$((${#arr[@]} + 1))
    local xor_all=0
    for ((i=1; i<=n; i++)); do
        xor_all=$((xor_all ^ i))
    done
    local xor_arr=0
    for num in "${arr[@]}"; do
        xor_arr=$((xor_arr ^ num))
    done
    echo $((xor_all ^ xor_arr))
}

arr=(1 2 4 5 6)
echo "Missing number: $(find_missing "${arr[@]}")"
echo "Missing number (XOR): $(find_missing_xor "${arr[@]}")"
Coding Round
55. Find duplicates

Find duplicates using associative arrays or sort | uniq -d.

  • Associative array: Count occurrences
  • sort: printf '%s\n' "{arr[@]}" | sort | uniq -d
  • Time: O(n) or O(n log n)
  • Returns: Duplicate values
bash
#!/bin/bash
# Find duplicates
find_duplicates() {
    local arr=("$@")
    local seen=()
    local dups=()
    for item in "${arr[@]}"; do
        local found=0
        for seen_item in "${seen[@]}"; do
            if [ "$seen_item" = "$item" ]; then
                found=1
                break
            fi
        done
        if [ $found -eq 1 ]; then
            local dup_found=0
            for dup in "${dups[@]}"; do
                if [ "$dup" = "$item" ]; then
                    dup_found=1
                    break
                fi
            done
            if [ $dup_found -eq 0 ]; then
                dups+=("$item")
            fi
        else
            seen+=("$item")
        fi
    done
    echo "${dups[@]}"
}

find_duplicates_count() {
    local arr=("$@")
    declare -A count
    for item in "${arr[@]}"; do
        count[$item]=$((count[$item] + 1))
    done
    local dups=()
    for key in "${!count[@]}"; do
        if [ ${count[$key]} -gt 1 ]; then
            dups+=("$key")
        fi
    done
    echo "${dups[@]}"
}

arr=(1 2 3 2 4 3 5 6 5)
echo "Original: ${arr[@]}"
echo "Duplicates: $(find_duplicates "${arr[@]}")"
echo "Duplicates (count): $(find_duplicates_count "${arr[@]}")"
Coding Round
56. Sum of array

Sum array elements using a loop or awk.

  • Loop: sum=0; for num in "{arr[@]}"; do sum=$((sum + num)); done
  • awk: printf '%s\n' "{arr[@]}" | awk '{sum+=$1} END {print sum}'
  • Empty: Returns 0
  • Time: O(n)
bash
#!/bin/bash
# Sum of array
sum_array() {
    local sum=0
    for num in "$@"; do
        sum=$((sum + num))
    done
    echo $sum
}

sum_array_manual() {
    local arr=("$@")
    local sum=0
    for ((i=0; i<${#arr[@]}; i++)); do
        sum=$((sum + arr[i]))
    done
    echo $sum
}

arr=(1 2 3 4 5)
echo "Array: ${arr[@]}"
echo "Sum: $(sum_array "${arr[@]}")"
echo "Sum (manual): $(sum_array_manual "${arr[@]}")"
Coding Round
57. Average of array

Calculate average by dividing sum by length.

  • Method: sum=0; count=0; for num in "{arr[@]}"; do sum=$((sum + num)); count=$((count + 1)); done; echo "scale=2; $sum / $count" | bc
  • Integer: echo $((sum / count))
  • Empty: Return 0
  • Time: O(n)
bash
#!/bin/bash
# Average of array
average_array() {
    local sum=0
    local count=0
    for num in "$@"; do
        sum=$((sum + num))
        count=$((count + 1))
    done
    echo "scale=2; $sum / $count" | bc
}

average_integer() {
    local sum=0
    local count=0
    for num in "$@"; do
        sum=$((sum + num))
        count=$((count + 1))
    done
    echo $((sum / count))
}

int_arr=(1 2 3 4 5)
float_arr=(1.0 2.0 3.0 4.0 5.0)
echo "Average (int array): $(average_array "${int_arr[@]}")"
echo "Average (integer): $(average_integer "${int_arr[@]}")"
Coding Round
58. Sort ascending

Sort arrays using sort -n or bubble sort.

  • sort: printf '%s\n' "{arr[@]}" | sort -n
  • Bubble sort: Custom implementation
  • Time: O(n log n) with sort
  • In-place: IFS=$'\n' read -ra sorted <<< "$(printf '%s\n' "{arr[@]}" | sort -n)"
bash
#!/bin/bash
# Sort ascending
sort_ascending() {
    printf '%s
' "$@" | sort -n
}

sort_ascending_inplace() {
    local arr=("$@")
    IFS=$'\n' read -ra sorted <<< "$(printf '%s
' "${arr[@]}" | sort -n)"
    arr=("${sorted[@]}")
}

arr=(5 2 8 1 9 3)
echo "Original: ${arr[@]}"
sorted=($(sort_ascending "${arr[@]}"))
echo "Sorted ascending: ${sorted[@]}"
sort_ascending_inplace "${arr[@]}"
echo "Sorted in-place: ${arr[@]}"
Coding Round
59. Sort descending

Sort descending using sort -nr or custom sort.

  • sort: printf '%s\n' "{arr[@]}" | sort -nr
  • Bubble sort: Reverse comparison
  • Time: O(n log n) with sort
  • In-place: Similar to ascending
bash
#!/bin/bash
# Sort descending
sort_descending() {
    printf '%s
' "$@" | sort -nr
}

sort_descending_inplace() {
    local arr=("$@")
    IFS=$'\n' read -ra sorted <<< "$(printf '%s
' "${arr[@]}" | sort -nr)"
    arr=("${sorted[@]}")
}

arr=(5 2 8 1 9 3)
echo "Original: ${arr[@]}"
sorted=($(sort_descending "${arr[@]}"))
echo "Sorted descending: ${sorted[@]}"
sort_descending_inplace "${arr[@]}"
echo "Sorted in-place: ${arr[@]}"
Coding Round
60. Flatten nested array

Flatten nested arrays using recursion or echo.

  • Recursive: flatten() { for item in "$@"; do ...; done }
  • Simple: echo "$@"
  • Time: O(n)
  • Depth: Handles nested structures
bash
#!/bin/bash
# Flatten nested array
flatten() {
    local result=()
    for item in "$@"; do
        if [[ "$item" =~ ^[0-9]+$ ]]; then
            result+=("$item")
        else
            local sub_result=($(flatten $item))
            result+=("${sub_result[@]}")
        fi
    done
    echo "${result[@]}"
}

# Simplified flatten using echo
flatten_simple() {
    echo "$@" | tr ' ' '\n' | sort -u
}

nested="1 2 3 4 5 6 7 8 9 10"
deeper="1 2 3 4 5 6 7 8 9 10"

echo "Nested: $nested"
echo "Flatten: $(flatten_simple "$nested")"
Coding Round
61. Chunk array

Split an array into chunks of a specified size.

  • Method: chunk_array() { local size=$1; shift; ... }
  • Loop: while [ $i -lt {#arr[@]} ]; do ...
  • Use case: Batch processing
  • Time: O(n)
bash
#!/bin/bash
# Chunk array
chunk_array() {
    local arr=("$@")
    local size=$1
    shift
    local result=()
    local chunk=()
    local count=0
    for item in "$@"; do
        chunk+=("$item")
        count=$((count + 1))
        if [ $count -eq $size ]; then
            result+=("${chunk[@]}")
            chunk=()
            count=0
        fi
    done
    if [ ${#chunk[@]} -gt 0 ]; then
        result+=("${chunk[@]}")
    fi
    echo "${result[@]}"
}

chunk_array_manual() {
    local arr=("$@")
    local size=$1
    shift
    local result=()
    local i=0
    while [ $i -lt ${#arr[@]} ]; do
        local end=$((i + size))
        if [ $end -gt ${#arr[@]} ]; then
            end=${#arr[@]}
        fi
        local chunk=()
        for ((j=i; j<end; j++)); do
            chunk+=("${arr[$j]}")
        done
        result+=("${chunk[@]}")
        i=$end
    done
    echo "${result[@]}"
}

arr=(1 2 3 4 5 6 7 8 9 10)
echo "Original: ${arr[@]}"
echo "Chunk (size 3):"
chunk_array 3 "${arr[@]}"
Coding Round
63. Quick sort

Implement quick sort with pivot and recursion.

  • Recursive: quick_sort() { ... }
  • Pivot: First element
  • Partition: Split into smaller/larger
  • Time: O(n log n) average
bash
#!/bin/bash
# Quick sort
quick_sort() {
    local arr=("$@")
    if [ ${#arr[@]} -le 1 ]; then
        echo "${arr[@]}"
        return
    fi
    local pivot=${arr[0]}
    local left=()
    local right=()
    for ((i=1; i<${#arr[@]}; i++)); do
        if [ ${arr[$i]} -lt $pivot ]; then
            left+=(${arr[$i]})
        else
            right+=(${arr[$i]})
        fi
    done
    local sorted_left=($(quick_sort "${left[@]}"))
    local sorted_right=($(quick_sort "${right[@]}"))
    echo "${sorted_left[@]} $pivot ${sorted_right[@]}"
}

arr=(5 3 8 4 2 7 1 6)
echo "Original: ${arr[@]}"
sorted=($(quick_sort "${arr[@]}"))
echo "Quick sort: ${sorted[@]}"
Coding Round
64. Merge sort

Implement merge sort with divide and conquer.

  • Divide: Split in half
  • Merge: Combine sorted halves
  • Time: O(n log n)
  • Space: O(n)
bash
#!/bin/bash
# Merge sort implementation

# Merge function - combines two sorted halves
merge() {
    local left=("$@")
    local right=()
    local mid=$((${#left[@]} / 2))
    
    # Split into left and right halves
    for ((i=0; i<mid; i++)); do
        right+=("${left[$i]}")
    done
    left=("${left[@]:mid}")
    
    local result=()
    local i=0 j=0
    
    # Merge the two sorted halves
    while [ $i -lt ${#left[@]} ] && [ $j -lt ${#right[@]} ]; do
        if [ ${left[$i]} -le ${right[$j]} ]; then
            result+=(${left[$i]})
            i=$((i + 1))
        else
            result+=(${right[$j]})
            j=$((j + 1))
        fi
    done
    
    # Append remaining elements from left (if any)
    while [ $i -lt ${#left[@]} ]; do
        result+=(${left[$i]})
        i=$((i + 1))
    done
    
    # Append remaining elements from right (if any)
    while [ $j -lt ${#right[@]} ]; do
        result+=(${right[$j]})
        j=$((j + 1))
    done
    
    echo "${result[@]}"
}

# Main merge_sort function
merge_sort() {
    local arr=("$@")
    
    # Base case: array with 0 or 1 element is already sorted
    if [ ${#arr[@]} -le 1 ]; then
        echo "${arr[@]}"
        return
    fi
    
    # Split array into two halves
    local mid=$((${#left[@]} / 2))
    local left=()
    local right=()
    
    for ((i=0; i<mid; i++)); do
        left+=(${arr[$i]})
    done
    
    for ((i=mid; i<${#arr[@]}; i++)); do
        right+=(${arr[$i]})
    done
    
    # Recursively sort both halves
    local sorted_left=($(merge_sort "${left[@]}"))
    local sorted_right=($(merge_sort "${right[@]}"))
    
    # Merge the sorted halves
    echo $(merge "${sorted_left[@]}" "${sorted_right[@]}")
}

# Usage example
arr=(5 3 8 4 2 7 1 6)
echo "Original: ${arr[@]}"
sorted=($(merge_sort "${arr[@]}"))
echo "Merge sort: ${sorted[@]}"
Coding Round
65. Bubble sort

Implement bubble sort with optimization.

  • Basic: for ((i=0; i<n-1; i++)); do for ((j=0; j<n-i-1; j++)); do if [ {arr[$j]} -gt {arr[$j+1]} ]; then swap; fi; done; done
  • Optimized: Track swaps
  • Time: O(n²)
  • Use case: Small arrays
bash
#!/bin/bash
# Bubble sort
bubble_sort() {
    local arr=("$@")
    local n=${#arr[@]}
    for ((i=0; i<n-1; i++)); do
        for ((j=0; j<n-i-1; j++)); do
            if [ ${arr[$j]} -gt ${arr[$j+1]} ]; then
                local temp=${arr[$j]}
                arr[$j]=${arr[$j+1]}
                arr[$j+1]=$temp
            fi
        done
    done
    echo "${arr[@]}"
}

bubble_sort_optimized() {
    local arr=("$@")
    local n=${#arr[@]}
    for ((i=0; i<n-1; i++)); do
        local swapped=0
        for ((j=0; j<n-i-1; j++)); do
            if [ ${arr[$j]} -gt ${arr[$j+1]} ]; then
                local temp=${arr[$j]}
                arr[$j]=${arr[$j+1]}
                arr[$j+1]=$temp
                swapped=1
            fi
        done
        if [ $swapped -eq 0 ]; then
            break
        fi
    done
    echo "${arr[@]}"
}

arr=(5 3 8 4 2 7 1 6)
echo "Original: ${arr[@]}"
echo "Bubble sort: $(bubble_sort "${arr[@]}")"
echo "Bubble sort optimized: $(bubble_sort_optimized "${arr[@]}")"
Coding Round
66. Intersection of arrays

Find common elements between two arrays.

  • Method: for item1 in "{arr1[@]}"; do for item2 in "{arr2[@]}"; do ...
  • Alternative: Use associative array
  • Time: O(n*m)
  • Unique: Remove duplicates
bash
#!/bin/bash
# Intersection of arrays
intersection() {
    local arr1=("${!1}")
    local arr2=("${!2}")
    local result=()
    for item1 in "${arr1[@]}"; do
        for item2 in "${arr2[@]}"; do
            if [ "$item1" = "$item2" ]; then
                local found=0
                for res in "${result[@]}"; do
                    if [ "$res" = "$item1" ]; then
                        found=1
                        break
                    fi
                done
                if [ $found -eq 0 ]; then
                    result+=("$item1")
                fi
                break
            fi
        done
    done
    echo "${result[@]}"
}

arr1=(apple banana orange grape kiwi)
arr2=(banana kiwi mango grape)
echo "Intersection: $(intersection arr1 arr2)"

ints1=(1 2 3 4 5)
ints2=(4 5 6 7 8)
echo "Intersection (ints): $(intersection ints1 ints2)"
Coding Round
67. Union of arrays

Combine arrays with unique elements.

  • Method: result=("{arr1[@]}"); for item in "{arr2[@]}"; do ...
  • Alternative: printf '%s\n' "{arr1[@]}" "{arr2[@]}" | sort -u
  • Time: O(n*m) or O(n log n) with sort
  • Preserve order: Manual method
bash
#!/bin/bash
# Union of arrays
union() {
    local arr1=("${!1}")
    local arr2=("${!2}")
    local result=("${arr1[@]}")
    for item in "${arr2[@]}"; do
        local found=0
        for res in "${result[@]}"; do
            if [ "$res" = "$item" ]; then
                found=1
                break
            fi
        done
        if [ $found -eq 0 ]; then
            result+=("$item")
        fi
    done
    echo "${result[@]}"
}

arr1=(apple banana orange)
arr2=(orange grape kiwi)
echo "Union: $(union arr1 arr2)"

ints1=(1 2 3 4)
ints2=(4 5 6 7)
echo "Union (ints): $(union ints1 ints2)"
Coding Round
68. Difference of arrays

Find elements in first array not in second.

  • Method: for item in "{arr1[@]}"; do found=0; for item2 in "{arr2[@]}"; do ...
  • Symmetric: Both directions
  • Time: O(n*m)
  • Returns: Difference
bash
#!/bin/bash
# Difference of arrays
difference() {
    local arr1=("${!1}")
    local arr2=("${!2}")
    local result=()
    for item in "${arr1[@]}"; do
        local found=0
        for item2 in "${arr2[@]}"; do
            if [ "$item" = "$item2" ]; then
                found=1
                break
            fi
        done
        if [ $found -eq 0 ]; then
            result+=("$item")
        fi
    done
    echo "${result[@]}"
}

symmetric_difference() {
    local arr1=("${!1}")
    local arr2=("${!2}")
    local diff1=($(difference arr1 arr2))
    local diff2=($(difference arr2 arr1))
    echo "${diff1[@]} ${diff2[@]}"
}

arr1=(apple banana orange grape)
arr2=(banana kiwi grape)
echo "Difference: $(difference arr1 arr2)"
echo "Symmetric difference: $(symmetric_difference arr1 arr2)"

ints1=(1 2 3 4 5)
ints2=(4 5 6 7 8)
echo "Difference (ints): $(difference ints1 ints2)"
Coding Round
69. Group by property

Group data by a property using associative arrays.

  • Method: declare -A groups; for item in ...; do key="{item#*:}"; groups[$key]="{groups[$key]} $item"; done
  • Use case: Data aggregation
  • Time: O(n)
  • Output: Grouped data
bash
#!/bin/bash
# Group by property
declare -A people
people[1]="Alice:25:NYC"
people[2]="Bob:30:LA"
people[3]="Charlie:25:NYC"
people[4]="David:35:Chicago"
people[5]="Eve:30:LA"

group_by_age() {
    local groups=()
    for key in "${!people[@]}"; do
        local person=${people[$key]}
        IFS=':' read -r name age city <<< "$person"
        local key="$age"
        groups+=("$key:$name")
    done
    echo "${groups[@]}"
}

group_by_city() {
    local groups=()
    for key in "${!people[@]}"; do
        local person=${people[$key]}
        IFS=':' read -r name age city <<< "$person"
        local key="$city"
        groups+=("$key:$name")
    done
    echo "${groups[@]}"
}

echo "Group by age:"
for group in $(group_by_age); do
    IFS=':' read -r age name <<< "$group"
    echo "Age $age: $name"
done

echo "Group by city:"
for group in $(group_by_city); do
    IFS=':' read -r city name <<< "$group"
    echo "City $city: $name"
done
Coding Round
70. Deep clone

Create a deep copy of an array or associative array.

  • Array: clone=("{original[@]}")
  • Associative: for key in "{!original[@]}"; do clone[$key]="{original[$key]}"; done
  • Nested: Recursive copy
  • Time: O(n)
bash
#!/bin/bash
# Deep clone (using eval)
deep_clone() {
    local var_name=$1
    local clone_name="${var_name}_clone"
    eval "$clone_name="${$var_name[@]}""
    eval "declare -a $clone_name=(${$var_name[@]})"
}

# Example
original=(1 2 3)
deep_clone original
eval "cloned=(${original_clone[@]})"
echo "Original: ${original[@]}"
echo "Cloned: ${cloned[@]}"

# Deep clone for associative arrays
deep_clone_assoc() {
    local var_name=$1
    local clone_name="${var_name}_clone"
    eval "declare -A $clone_name"
    eval "for key in "${!$var_name[@]}"; do $clone_name[$key]="${$var_name[$key]}"; done"
}

declare -A map
map[name]="Alice"
map[age]=25
deep_clone_assoc map
eval "declare -A map_clone"
eval "for key in "${!map_clone[@]}"; do echo "$key => ${map_clone[$key]}"; done"
Coding Round
71. Immutable update

Perform immutable updates by copying and modifying.

  • Method: clone=("{original[@]}"); clone[$index]="$value"
  • Nested: Copy and update nested
  • Return: New array
  • Use case: State management
bash
#!/bin/bash
# Immutable update
update_immutable() {
    local var_name=$1
    local path=$2
    local value=$3
    eval "local clone=(${$var_name[@]})"
    eval "clone[$path]="$value""
    echo "${clone[@]}"
}

# Nested update (using associative arrays)
update_nested() {
    local var_name=$1
    local key=$2
    local value=$3
    eval "declare -A clone"
    eval "for k in "${!$var_name[@]}"; do clone[$k]="${$var_name[$k]}"; done"
    eval "clone[$key]="$value""
    echo "${clone[@]}"
}

state=(name Alice age 25)
new_state=($(update_immutable state 1 Bob))
echo "Original: ${state[@]}"
echo "Updated: ${new_state[@]}"

declare -A person
person[name]="Alice"
person[age]=25
person[city]="NYC"
# Update age
eval "new_person=($(update_nested person age 26))"
echo "Original: ${person[@]}"
echo "Updated: ${new_person[@]}"
Coding Round
72. Pipe function

Implement pipe for left-to-right function composition.

  • Method: pipe() { value=$1; shift; for func in "$@"; do value=$($func "$value"); done; echo "$value"; }
  • Direction: Left to right
  • Use case: Function chaining
  • Implementation: Loop functions
bash
#!/bin/bash
# Pipe function
pipe() {
    local value=$1
    shift
    for func in "$@"; do
        value=$($func "$value")
    done
    echo "$value"
}

double() { echo $(( $1 * 2 )); }
add_ten() { echo $(( $1 + 10 )); }
square() { echo $(( $1 * $1 )); }

result=$(pipe 5 double add_ten square)
echo "Pipe: $result"

# Using pipeline with functions
double_pipe() { while read -r x; do echo $((x * 2)); done; }
add_ten_pipe() { while read -r x; do echo $((x + 10)); done; }
square_pipe() { while read -r x; do echo $((x * x)); done; }

result2=$(echo 5 | double_pipe | add_ten_pipe | square_pipe)
echo "Pipeline: $result2"
Coding Round
73. Compose function

Implement compose for right‑to‑left function composition.

  • Method:compose() { result=$1; shift; for ((i=${#@}-1; i>=0; i--)); do result=${@:$i:1} "$result"); done; echo "$result"; }
  • Direction: Right to left
  • Use case: Function composition
  • Alternative: compose_alt
bash
#!/bin/bash
# Compose function
compose() {
    local funcs=("$@")
    local result=$1
    shift
    for ((i=${#funcs[@]}-1; i>=0; i--)); do
        result=$(${funcs[$i]} "$result")
    done
    echo "$result"
}

double() { echo $(( $1 * 2 )); }
add_ten() { echo $(( $1 + 10 )); }
square() { echo $(( $1 * $1 )); }

result=$(compose 5 double add_ten square)
echo "Composed: $result"

# Alternative compose
compose_alt() {
    local funcs=("$@")
    local value=$1
    shift
    for func in "${funcs[@]}"; do
        value=$($func "$value")
    done
    echo "$value"
}

result2=$(compose_alt 5 square add_ten double)
echo "Composed alt: $result2"
Coding Round
74. Memoization

Implement memoization using associative arrays.

  • Cache: declare -A cache
  • Check: [[ -v cache[$key] ]]
  • Store: cache[$key]="$result"
  • File cache: Use temporary files
bash
#!/bin/bash
# Memoization
declare -A memo_cache

memoize() {
    local func=$1
    local arg=$2
    local cache_key="${func}_$arg"
    if [ -n "${memo_cache[$cache_key]}" ]; then
        echo "${memo_cache[$cache_key]}"
        return
    fi
    local result=$($func $arg)
    memo_cache[$cache_key]=$result
    echo $result
}

fib() {
    if [ $1 -le 1 ]; then
        echo $1
    else
        local a=$(memoize fib $(( $1 - 1 )))
        local b=$(memoize fib $(( $1 - 2 )))
        echo $((a + b))
    fi
}

echo "Fibonacci(10): $(fib 10)"
echo "Fibonacci(10) again: $(fib 10)"

# Using file-based cache
memoize_file() {
    local func=$1
    local arg=$2
    local cache_dir="/tmp/memo_cache"
    mkdir -p "$cache_dir"
    local cache_file="$cache_dir/${func}_$arg"
    if [ -f "$cache_file" ]; then
        cat "$cache_file"
        return
    fi
    local result=$($func $arg)
    echo "$result" > "$cache_file"
    echo $result
}
Coding Round
75. Once function

Implement once function that ensures a function is called only once.

  • Flag: called=0
  • Check: if [ $called -eq 0 ]; then ...
  • Result: Cache result
  • Reset: Reset flag
bash
#!/bin/bash
# Once function
declare -A once_called
declare -A once_results

once() {
    local func=$1
    local arg=$2
    local key="${func}_$arg"
    if [ -n "${once_called[$key]}" ]; then
        echo "${once_results[$key]}"
        return
    fi
    once_called[$key]=1
    local result=$($func $arg)
    once_results[$key]=$result
    echo $result
}

initialize() {
    echo "Initialized with $1"
    echo $(( $1 * 2 ))
}

echo "First: $(once initialize 10)"
echo "Second: $(once initialize 20)"

# Once with reset
once_with_reset() {
    local func=$1
    local arg=$2
    local key="${func}_$arg"
    if [ -n "${once_called[$key]}" ]; then
        echo "${once_results[$key]}"
        return
    fi
    once_called[$key]=1
    local result=$($func $arg)
    once_results[$key]=$result
    echo $result
}

reset_once() {
    local func=$1
    local arg=$2
    local key="${func}_$arg"
    unset once_called[$key]
    unset once_results[$key]
}

init() {
    echo "Initialized with $1"
    echo $(( $1 * 2 ))
}

echo "First: $(once_with_reset init 10)"
reset_once init 10
echo "After reset: $(once_with_reset init 20)"
Coding Round
76. Debounce with leading edge

Implement debounce with leading edge using timers.

  • Last call: Track time
  • Execute: If enough time passed
  • Timeout: Schedule delayed execution
  • Use case: Rate limiting
bash
#!/bin/bash
# Debounce with leading edge
declare -A debounce_last_call
declare -A debounce_timeout

debounce_leading() {
    local func=$1
    local delay=$2
    local arg=$3
    local key="${func}_$arg"
    local now=$(date +%s)
    if [ -z "${debounce_last_call[$key]}" ] || [ $((now - debounce_last_call[$key])) -ge $delay ]; then
        debounce_last_call[$key]=$now
        $func $arg
    else
        if [ -z "${debounce_timeout[$key]}" ]; then
            (
                sleep $((delay - (now - debounce_last_call[$key])))
                debounce_last_call[$key]=$(date +%s)
                $func $arg
                unset debounce_timeout[$key]
            ) &
            debounce_timeout[$key]=1
        fi
    fi
}

process() {
    echo "Processing: $1"
}

debounce_leading process 2 "value1"
debounce_leading process 2 "value2"
sleep 3
debounce_leading process 2 "value3"
Coding Round
77. Throttle with leading edge

Implement throttle with leading edge by checking time since last call.

  • Last call: Track time
  • Execute: If enough time passed
  • Trailing: Schedule pending execution
  • Use case: Scroll events
bash
#!/bin/bash
# Throttle with leading edge
declare -A throttle_last_call

throttle_leading() {
    local func=$1
    local delay=$2
    local arg=$3
    local key="${func}_$arg"
    local now=$(date +%s)
    if [ -z "${throttle_last_call[$key]}" ] || [ $((now - throttle_last_call[$key])) -ge $delay ]; then
        throttle_last_call[$key]=$now
        $func $arg
    fi
}

process() {
    echo "Processing: $1"
}

throttle_leading process 2 "value1"
throttle_leading process 2 "value2"
sleep 3
throttle_leading process 2 "value3"

# Throttle with trailing
declare -A throttle_pending
declare -A throttle_timer

throttle_trailing() {
    local func=$1
    local delay=$2
    local arg=$3
    local key="${func}_$arg"
    local now=$(date +%s)
    if [ -z "${throttle_last_call[$key]}" ] || [ $((now - throttle_last_call[$key])) -ge $delay ]; then
        throttle_last_call[$key]=$now
        $func $arg
    else
        throttle_pending[$key]=$arg
        if [ -z "${throttle_timer[$key]}" ]; then
            local remaining=$((delay - (now - throttle_last_call[$key])))
            (
                sleep $remaining
                throttle_last_call[$key]=$(date +%s)
                if [ -n "${throttle_pending[$key]}" ]; then
                    $func ${throttle_pending[$key]}
                    unset throttle_pending[$key]
                fi
                unset throttle_timer[$key]
            ) &
            throttle_timer[$key]=1
        fi
    fi
}
Coding Round
78. Deep equal

Implement deep equality for arrays and associative arrays.

  • Method: deep_equal() { local -n arr1=$1; local -n arr2=$2; ... }
  • Length: Must be equal
  • Elements: Compare each
  • Types: Check array types
bash
#!/bin/bash
# Deep equal
deep_equal() {
    if [ "$1" = "$2" ]; then
        return 0
    fi
    local type1=$(declare -p "$1" 2>/dev/null)
    local type2=$(declare -p "$2" 2>/dev/null)
    if [ "$type1" != "$type2" ]; then
        return 1
    fi
    eval "local arr1=(${$1[@]})"
    eval "local arr2=(${$2[@]})"
    if [ ${#arr1[@]} -ne ${#arr2[@]} ]; then
        return 1
    fi
    for ((i=0; i<${#arr1[@]}; i++)); do
        if [ "${arr1[$i]}" != "${arr2[$i]}" ]; then
            return 1
        fi
    done
    return 0
}

arr1=(1 2 3)
arr2=(1 2 3)
arr3=(1 2 4)

if deep_equal arr1 arr2; then
    echo "arr1 == arr2"
else
    echo "arr1 != arr2"
fi

if deep_equal arr1 arr3; then
    echo "arr1 == arr3"
else
    echo "arr1 != arr3"
fi

# Deep equal for associative arrays
deep_equal_assoc() {
    local -n arr1=$1
    local -n arr2=$2
    if [ ${#arr1[@]} -ne ${#arr2[@]} ]; then
        return 1
    fi
    for key in "${!arr1[@]}"; do
        if [ "${arr1[$key]}" != "${arr2[$key]}" ]; then
            return 1
        fi
    done
    return 0
}

declare -A map1 map2 map3
map1[name]="Alice"; map1[age]=25
map2[name]="Alice"; map2[age]=25
map3[name]="Alice"; map3[age]=26

if deep_equal_assoc map1 map2; then
    echo "map1 == map2"
fi
if deep_equal_assoc map1 map3; then
    echo "map1 == map3"
fi
Coding Round
79. Observable pattern

Implement observable pattern with subscribers and notification.

  • Subscribers: Associative array
  • Subscribe: subscribers[$id]="$callback"
  • Notify: for id in "{!subscribers[@]}"; do {subscribers[$id]} "$data"; done
  • Stateful: Track state
bash
#!/bin/bash
# Observable pattern
declare -A subscribers

observable() {
    local action=$1
    shift
    case $action in
        subscribe)
            local id=$1
            local callback=$2
            subscribers[$id]=$callback
            ;;
        unsubscribe)
            local id=$1
            unset subscribers[$id]
            ;;
        notify)
            local data=$1
            for id in "${!subscribers[@]}"; do
                ${subscribers[$id]} "$data"
            done
            ;;
    esac
}

# Stateful observable
declare -A stateful_subscribers
stateful_observable() {
    local action=$1
    shift
    case $action in
        subscribe)
            local id=$1
            local callback=$2
            stateful_subscribers[$id]=$callback
            ;;
        set_state)
            local data=$1
            state=$data
            for id in "${!stateful_subscribers[@]}"; do
                ${stateful_subscribers[$id]} "$data"
            done
            ;;
        get_state)
            echo "$state"
            ;;
    esac
}

# Usage
observable subscribe "observer1" "echo 'Observer1: $1'"
observable subscribe "observer2" "echo 'Observer2: $1'"
observable notify "Hello, World!"

observable unsubscribe "observer1"
observable notify "Hello again!"

stateful_observable set_state "Initial"
stateful_observable subscribe "state_obs" "echo 'State changed to: $1'"
stateful_observable set_state "New State"
Coding Round
80. Singleton pattern

Implement singleton pattern using associative arrays or variables.

  • Instance: singleton_data[$class]="initialized"
  • Check: if [ -z "{singleton_data[$class]}" ]; then ...
  • Return: Existing instance
  • Factory: Create on demand
bash
#!/bin/bash
# Singleton pattern
declare -A singleton_data

get_singleton() {
    local class=$1
    if [ -z "${singleton_data[$class]}" ]; then
        singleton_data[$class]="initialized"
        echo "Creating singleton for $class"
    fi
    echo "${singleton_data[$class]}"
}

# Singleton with data
declare -A singleton_instances

singleton() {
    local class=$1
    if [ -z "${singleton_instances[$class]}" ]; then
        singleton_instances[$class]="instance"
        echo "Singleton $class created"
    fi
    echo "${singleton_instances[$class]}"
}

# Singleton factory
singleton_factory() {
    local instance_var="singleton_${1}_instance"
    if [ -z "${!instance_var}" ]; then
        eval "$instance_var='created'"
        echo "Singleton created: $1"
    fi
    eval "echo $$instance_var"
}

# Usage
get_singleton "config"
get_singleton "config"

singleton "database"
singleton "database"

singleton_factory "logger"
singleton_factory "logger"

# Singleton with data storage
declare -A singleton_store

singleton_store_init() {
    local name=$1
    if [ -z "${singleton_store[$name]}" ]; then
        singleton_store[$name]="{}"
        echo "Store $name initialized"
    fi
    echo "${singleton_store[$name]}"
}

singleton_store_set() {
    local name=$1
    local key=$2
    local value=$3
    local data=$(singleton_store_init "$name")
    # Simple key-value storage
    eval "declare -A temp"
    eval "temp=($data)"
    temp[$key]=$value
    local new_data=""
    for k in "${!temp[@]}"; do
        new_data="$new_data $k=${temp[$k]}"
    done
    singleton_store[$name]="$new_data"
}

singleton_store_get() {
    local name=$1
    local key=$2
    local data=$(singleton_store_init "$name")
    eval "declare -A temp"
    eval "temp=($data)"
    echo "${temp[$key]:-}"
}
Coding Round
81. Factory pattern

Implement factory pattern for creating objects with different types.

  • Factory: create_user() { case $type in ... }
  • Types: admin, guest, regular
  • Parameters: name, permissions
  • Return: User string
bash
#!/bin/bash
# Factory pattern
create_user() {
    local type=$1
    local name=$2
    case $type in
        admin)
            echo "admin:$name"
            ;;
        guest)
            echo "guest:$name"
            ;;
        *)
            echo "regular:$name"
            ;;
    esac
}

# User factory with validation
user_factory() {
    local type=$1
    local name=$2
    if [ -z "$name" ]; then
        echo "Error: Name is required" >&2
        return 1
    fi
    create_user "$type" "$name"
}

# Factory with permissions
create_user_with_permissions() {
    local type=$1
    local name=$2
    local permissions=$3
    case $type in
        admin)
            echo "admin:$name:$permissions"
            ;;
        guest)
            echo "guest:$name:"
            ;;
        *)
            echo "regular:$name:"
            ;;
    esac
}

# Usage
user1=$(create_user admin Alice)
user2=$(create_user guest Bob)
user3=$(create_user regular Charlie)

echo "$user1"
echo "$user2"
echo "$user3"

user4=$(user_factory admin "Alice")
user5=$(user_factory guest "Bob")

echo "$user4"
echo "$user5"
Coding Round
82. Strategy pattern

Implement strategy pattern with interchangeable strategies.

  • Strategies: Functions
  • Context: payment_context() { case $strategy in ... }
  • Execute: Call selected strategy
  • Decorator: Add discount
bash
#!/bin/bash
# Strategy pattern
credit_card_payment() {
    echo "Paid $1 with Credit Card"
}

paypal_payment() {
    echo "Paid $1 with PayPal"
}

crypto_payment() {
    echo "Paid $1 with Crypto"
}

payment_context() {
    local strategy=$1
    local amount=$2
    case $strategy in
        credit)
            credit_card_payment "$amount"
            ;;
        paypal)
            paypal_payment "$amount"
            ;;
        crypto)
            crypto_payment "$amount"
            ;;
        *)
            echo "Unknown strategy"
            ;;
    esac
}

# Strategy with discount
discount_decorator() {
    local strategy=$1
    local discount=$2
    local amount=$3
    local discounted=$(echo "$amount * (1 - $discount)" | bc)
    echo "Applied discount of $(($discount * 100))%"
    payment_context "$strategy" "$discounted"
}

# Usage
payment_context credit 100
payment_context paypal 50
payment_context crypto 75

discount_decorator paypal 0.1 100
Coding Round
83. Observer pattern

Implement observer pattern with subject and observers.

  • Subject: subject() { case $action in attach|detach|notify) ... }
  • Observers: Associative array
  • Attach: Add observer
  • Notify: Call all observers
bash
#!/bin/bash
# Observer pattern
declare -A observers

subject() {
    local action=$1
    shift
    case $action in
        attach)
            local id=$1
            local callback=$2
            observers[$id]=$callback
            ;;
        detach)
            local id=$1
            unset observers[$id]
            ;;
        notify)
            local data=$1
            for id in "${!observers[@]}"; do
                ${observers[$id]} "$data"
            done
            ;;
    esac
}

# Concrete subject with state
declare -A stateful_observers
subject_state=""

stateful_subject() {
    local action=$1
    shift
    case $action in
        attach)
            local id=$1
            local callback=$2
            stateful_observers[$id]=$callback
            ;;
        detach)
            local id=$1
            unset stateful_observers[$id]
            ;;
        set_state)
            subject_state=$1
          for id in "${!stateful_observers[@]}"; do
                ${stateful_observers[$id]} "$subject_state"
            done
            ;;
        get_state)
            echo "$subject_state"
            ;;
    esac
}

# Usage
subject attach "obs1" "echo 'Observer1: $1'"
subject attach "obs2" "echo 'Observer2: $1'"

subject notify "Hello, World!"

subject detach "obs1"
subject notify "Hello again!"

stateful_subject attach "state_obs" "echo 'State changed to: $1'"
stateful_subject set_state "Initial State"
stateful_subject set_state "New State"
Coding Round
84. Decorator pattern

Implement decorator pattern for adding features.

  • Component: basic_coffee() { echo "Coffee"; echo "5.0"; }
  • Decorators: milk_decorator() { ... }
  • Chaining: apply_decorators() { for decorator in "$@"; do ... }
  • Composition: Nested calls
bash
#!/bin/bash
# Decorator pattern
basic_coffee() {
    echo "Coffee"
    echo "5.0"
}

milk_decorator() {
    local desc=$1
    local cost=$2
    echo "$desc, Milk"
    echo "$cost + 2.0" | bc
}

sugar_decorator() {
    local desc=$1
    local cost=$2
    echo "$desc, Sugar"
    echo "$cost + 1.0" | bc
}

caramel_decorator() {
    local desc=$1
    local cost=$2
    echo "$desc, Caramel"
    echo "$cost + 2.5" | bc
}

whipped_cream_decorator() {
    local desc=$1
    local cost=$2
    echo "$desc, Whipped Cream"
    echo "$cost + 1.5" | bc
}

apply_decorators() {
    local desc="Coffee"
    local cost="5.0"
    for decorator in "$@"; do
        case $decorator in
            milk)
                local result=$(milk_decorator "$desc" "$cost")
                desc=$(echo "$result" | head -1)
                cost=$(echo "$result" | tail -1)
                ;;
            sugar)
                local result=$(sugar_decorator "$desc" "$cost")
                desc=$(echo "$result" | head -1)
                cost=$(echo "$result" | tail -1)
                ;;
            caramel)
                local result=$(caramel_decorator "$desc" "$cost")
                desc=$(echo "$result" | head -1)
                cost=$(echo "$result" | tail -1)
                ;;
            whipped)
                local result=$(whipped_cream_decorator "$desc" "$cost")
                desc=$(echo "$result" | head -1)
                cost=$(echo "$result" | tail -1)
                ;;
        esac
    done
    echo "$desc ($cost)"
}

# Usage
basic_coffee
milk_decorator "Coffee" "5.0"
sugar_decorator "Coffee" "5.0"
apply_decorators milk sugar caramel whipped
Coding Round
85. Command pattern

Implement command pattern with execute, undo, and redo.

  • Command: add_command() { counter=$((counter + value)); command_history+=("add:$value"); }
  • Undo: undo() { last={command_history[-1]}; ... }
  • Redo: Re-execute commands
  • History: Store commands
bash
#!/bin/bash
# Command pattern
declare -a command_history
declare -a command_results

add_command() {
    local value=$1
    counter=$((counter + value))
    command_history+=("add:$value")
}

subtract_command() {
    local value=$1
    counter=$((counter - value))
    command_history+=("subtract:$value")
}

undo() {
    if [ ${#command_history[@]} -gt 0 ]; then
        local last=${command_history[-1]}
        unset 'command_history[-1]'
        local cmd=${last%:*}
        local value=${last#*:}
        case $cmd in
            add) counter=$((counter - value));;
            subtract) counter=$((counter + value));;
        esac
    fi
}

redo() {
    # Re-execute commands from history
    local cmd=${command_history[-1]}
    case $cmd in
        add:*) add_command ${cmd#*:};;
        subtract:*) subtract_command ${cmd#*:};;
    esac
}

macro_command() {
    for cmd in "$@"; do
        case $cmd in
            add:*) add_command ${cmd#*:};;
            subtract:*) subtract_command ${cmd#*:};;
        esac
    done
}

# Usage
counter=0
add_command 5
echo "Counter: $counter"
subtract_command 3
echo "Counter: $counter"
undo
echo "After undo: $counter"

macro_command "add:5" "add:5" "subtract:3"
echo "After macro: $counter"
Coding Round
86. Memento pattern

Implement memento pattern for state capture and restoration.

  • Save: save_state() { mementos+=("$1"); }
  • Restore: restore_state() { local state={mementos[-1]}; unset 'mementos[-1]'; echo "$state"; }
  • Originator: Holds state
  • Caretaker: Manages mementos
bash
#!/bin/bash
# Memento pattern
declare -a mementos
declare -a memento_states

save_state() {
    local state=$1
    mementos+=("$state")
}

restore_state() {
    if [ ${#mementos[@]} -gt 0 ]; then
        local state=${mementos[-1]}
        unset 'mementos[-1]'
        echo "$state"
    fi
}

# Originator
originator_state=""

set_originator_state() {
    originator_state=$1
    save_state "$originator_state"
}

get_originator_state() {
    echo "$originator_state"
}

# Usage
set_originator_state 0
set_originator_state 1
set_originator_state 2
set_originator_state 3

echo "Current: $(get_originator_state)"
restored=$(restore_state)
echo "After undo: $restored"
restored=$(restore_state)
echo "After redo: $restored"

# Memento with caretaker
declare -a caretaker_mementos
declare -a caretaker_index

caretaker_save() {
    local state=$1
    caretaker_mementos+=("$state")
}

caretaker_undo() {
    if [ ${#caretaker_mementos[@]} -gt 0 ]; then
        local state=${caretaker_mementos[-1]}
        unset 'caretaker_mementos[-1]'
        echo "$state"
    fi
}

caretaker_redo() {
    # Re-apply mementos
    if [ ${#caretaker_mementos[@]} -gt 0 ]; then
        echo "${caretaker_mementos[-1]}"
    fi
}
Coding Round
87. Mediator pattern

Implement mediator pattern for centralized communication.

  • Mediator: mediator() { case $action in register|send) ... }
  • Colleagues: Associate array of callbacks
  • Register: Add colleague
  • Send: Route messages
bash
#!/bin/bash
# Mediator pattern
declare -A mediator_colleagues

mediator() {
    local action=$1
    shift
    case $action in
        register)
            local name=$1
            local callback=$2
            mediator_colleagues[$name]=$callback
            ;;
        send)
            local message=$1
            local sender=$2
            for name in "${!mediator_colleagues[@]}"; do
                if [ "$name" != "$sender" ]; then
                    ${mediator_colleagues[$name]} "$message"
                fi
            done
            ;;
    esac
}

# Colleague
colleague() {
    local name=$1
    local receive_func=$2
    echo "$name"
}

# Usage
mediator register "Alice" "echo 'Alice received: $1'"
mediator register "Bob" "echo 'Bob received: $1'"
mediator register "Charlie" "echo 'Charlie received: $1'"

mediator send "Hello everyone!" "Alice"

# Stateful colleague
declare -A colleague_states

stateful_colleague() {
    local name=$1
    local state=$2
    colleague_states[$name]=$state
    mediator register "$name" "echo '$name (state $state) received: $1'"
}

stateful_colleague "Alice" 0
stateful_colleague "Bob" 1
mediator send "Custom message" "Alice"
Coding Round
88. Chain of Responsibility

Implement chain of responsibility with linked handlers.

  • Handlers: auth, logger, validator
  • Chain: chain_handlers[$handler]="$next"
  • Process: handler handle "$handler" "$request"
  • Stop: On failure
bash
#!/bin/bash
# Chain of Responsibility
declare -A chain_handlers

handler() {
    local action=$1
    shift
    case $action in
        set_next)
            local handler=$1
            local next=$2
            chain_handlers[$handler]=$next
            ;;
        handle)
            local handler=$1
            local request=$2
            case $handler in
                auth)
                    if echo "$request" | grep -q "token"; then
                        echo "Authentication passed"
                        local next=${chain_handlers[$handler]}
                        if [ -n "$next" ]; then
                            handler handle "$next" "$request"
                        fi
                    else
                        echo "Authentication failed"
                    fi
                    ;;
                logger)
                    local url=$(echo "$request" | grep -o "url=[^&]*" | cut -d= -f2)
                    echo "Logging request: ${url:-unknown}"
                    local next=${chain_handlers[$handler]}
                    if [ -n "$next" ]; then
                        handler handle "$next" "$request"
                    fi
                    ;;
                validator)
                    if echo "$request" | grep -q "data"; then
                        echo "Validation passed"
                        local next=${chain_handlers[$handler]}
                        if [ -n "$next" ]; then
                            handler handle "$next" "$request"
                        fi
                    else
                        echo "Validation failed"
                    fi
                    ;;
                ratelimit)
                    echo "Rate limit passed"
                    local next=${chain_handlers[$handler]}
                    if [ -n "$next" ]; then
                        handler handle "$next" "$request"
                    fi
                    ;;
            esac
            ;;
    esac
}

# Setup chain
handler set_next "auth" "logger"
handler set_next "logger" "validator"
handler set_next "validator" "ratelimit"

# Usage
echo "Processing valid request:"
handler handle "auth" "token=valid&url=/api&data=payload"

echo "Processing invalid request:"
handler handle "auth" "url=/public"
Coding Round
89. State pattern

Implement state pattern with context and state transitions.

  • Context: current_state="ready"
  • States: handle_state() { case $current_state in ready|processing|completed) ... }
  • Transition: Change state
  • Data: Track state data
bash
#!/bin/bash
# State pattern
current_state="ready"

handle_state() {
    case $current_state in
        ready)
            echo "Ready: Waiting for input"
            current_state="processing"
            ;;
        processing)
            echo "Processing: Working on task"
            current_state="completed"
            ;;
        completed)
            echo "Completed: Task finished"
            current_state="ready"
            ;;
        error)
            echo "Error: Something went wrong"
            current_state="ready"
            ;;
    esac
}

# State with data
declare -A state_data

stateful_context() {
    local state=$1
    case $state in
        ready)
            echo "Ready: Waiting for input"
            state_data["last_state"]="ready"
            current_state="processing"
            ;;
        processing)
            echo "Processing: Working on task"
            state_data["last_state"]="processing"
            current_state="completed"
            ;;
        completed)
            echo "Completed: Task finished"
            state_data["last_state"]="completed"
            current_state="ready"
            ;;
        error)
            echo "Error: Something went wrong"
            state_data["last_state"]="error"
            current_state="ready"
            ;;
    esac
}

# Usage
for i in {1..5}; do
    echo "Step $i:"
    handle_state
    echo "State data: ${state_data["last_state"]:-none}"
done
Coding Round
90. Proxy pattern

Implement proxy pattern for access control and lazy initialization.

  • Real subject: real_subject() { echo "RealSubject: Handling request"; }
  • Proxy: proxy() { if [ -z "$cached_subject" ]; then ... }
  • Logging: logging_proxy() { echo "Logging"; real_subject; }
  • Auth: auth_proxy() { [ "$user" = "admin" ] && real_subject; }
bash
#!/bin/bash
# Proxy pattern
real_subject() {
    echo "RealSubject: Handling request"
}

proxy() {
    if [ -z "$cached_subject" ]; then
        echo "Proxy: Creating real subject"
        cached_subject="created"
    fi
    echo "Proxy: Using cached real subject"
    real_subject
}

logging_proxy() {
    echo "Logging: Request started"
    real_subject
    echo "Logging: Request completed"
}

auth_proxy() {
    local user=$1
    if [ "$user" = "admin" ]; then
        echo "Auth: Access granted"
        real_subject
    else
        echo "Auth: Access denied"
        echo "Unauthorized"
    fi
}

# Usage
echo "$(proxy)"
echo "$(proxy)"

echo "$(logging_proxy)"

echo "$(auth_proxy admin)"
echo "$(auth_proxy guest)"

# Proxy with caching
declare -A proxy_cache

caching_proxy() {
    local key=$1
    if [ -n "${proxy_cache[$key]}" ]; then
        echo "Cache hit: ${proxy_cache[$key]}"
    else
        local result=$(real_subject)
        proxy_cache[$key]=$result
        echo "Cache miss: $result"
    fi
}
Coding Round
91. Flyweight pattern

Implement flyweight pattern for sharing objects.

  • Flyweight: flyweight() { echo "flyweight_$1"; }
  • Factory: flyweight_cache[$shared_state]="flyweight_$shared_state"
  • Operation: flyweight_operation() { echo "Shared: $flyweight, Unique: $unique_state"; }
  • Share: Reuse instances
bash
#!/bin/bash
# Flyweight pattern
declare -A flyweight_cache

flyweight() {
    local shared_state=$1
    if [ -z "${flyweight_cache[$shared_state]}" ]; then
        flyweight_cache[$shared_state]="flyweight_$shared_state"
    fi
    echo "${flyweight_cache[$shared_state]}"
}

flyweight_operation() {
    local flyweight=$1
    local unique_state=$2
    echo "Shared: $flyweight, Unique: $unique_state"
}

# Usage
fw1=$(flyweight "state1")
fw2=$(flyweight "state1")
fw3=$(flyweight "state2")

echo "fw1 and fw2 are same: $([ "$fw1" = "$fw2" ] && echo "true" || echo "false")"
echo "fw1 and fw3 are same: $([ "$fw1" = "$fw3" ] && echo "true" || echo "false")"

flyweight_operation "$fw1" "unique1"
flyweight_operation "$fw2" "unique2"
flyweight_operation "$fw3" "unique3"

echo "Number of flyweights: ${#flyweight_cache[@]}"
Coding Round
92. Bridge pattern

Implement bridge pattern for separating abstraction from implementation.

  • Implementation: impl_a() { echo "ConcreteImplementationA: Operation"; }
  • Abstraction: abstraction() { case $impl in A|B) ... }
  • Extended: extended_abstraction() { ... }
  • Alternative: alternative_abstraction() { ... }
bash
#!/bin/bash
# Bridge pattern
impl_a() {
    echo "ConcreteImplementationA: Operation"
}

impl_b() {
    echo "ConcreteImplementationB: Operation"
}

abstraction() {
    local impl=$1
    case $impl in
        A) echo "Abstraction: Additional logic - $(impl_a)";;
        B) echo "Abstraction: Additional logic - $(impl_b)";;
    esac
}

extended_abstraction() {
    local impl=$1
    case $impl in
        A) echo "Extended: More logic - $(impl_a)";;
        B) echo "Extended: More logic - $(impl_b)";;
    esac
}

alternative_abstraction() {
    local impl=$1
    case $impl in
        A) echo "Alternative: Different logic - $(impl_a)";;
        B) echo "Alternative: Different logic - $(impl_b)";;
    esac
}

# Usage
abstraction A
abstraction B
extended_abstraction A
extended_abstraction B
alternative_abstraction A
alternative_abstraction B
Coding Round
93. Adapter pattern

Implement adapter pattern for converting interfaces.

  • Target: target() { echo "Target: Request"; }
  • Adaptee: adaptee() { echo "Adaptee: Specific Request"; }
  • Adapter: adapter() { adaptee; }
  • Logging: logging_adapter() { echo "Logging"; adaptee; }
bash
#!/bin/bash
# Adapter pattern
target() {
    echo "Target: Request"
}

adaptee() {
    echo "Adaptee: Specific Request"
}

adapter() {
    adaptee
}

logging_adapter() {
    echo "Adapter: Logging request"
    adaptee
}

# Usage
echo "$(target)"
echo "$(adapter)"
echo "$(logging_adapter)"

# Adapter with conversion
numeric_adapter() {
    local input=$1
    echo "$((input * 2))"
}

string_adapter() {
    local input=$1
    echo "Converted: $input"
}

adapter_with_conversion() {
    local type=$1
    local data=$2
    case $type in
        numeric) numeric_adapter "$data";;
        string) string_adapter "$data";;
    esac
}
Coding Round
94. Facade pattern

Implement facade pattern for simplifying complex subsystems.

  • Subsystems: subsystem_a() { echo "SubsystemA: Operation"; }
  • Facade: facade() { case $type in simple|complex) ... }
  • Simplified: simplified_facade() { facade simple; }
  • Config: facade_config() { case $config in minimal|standard|full) ... }
bash
#!/bin/bash
# Facade pattern
subsystem_a() {
    echo "SubsystemA: Operation"
}

subsystem_b() {
    echo "SubsystemB: Operation"
}

subsystem_c() {
    echo "SubsystemC: Operation"
}

facade() {
    local type=$1
    case $type in
        simple)
            subsystem_a
            ;;
        complex)
            subsystem_a
            subsystem_b
            subsystem_c
            ;;
    esac
}

simplified_facade() {
    facade simple
}

# Usage
echo "Simple operation:"
facade simple

echo "Complex operation:"
facade complex

echo "Simplified facade:"
simplified_facade

# Facade with configuration
facade_config() {
    local config=$1
    case $config in
        minimal)
            subsystem_a
            ;;
        standard)
            subsystem_a
            subsystem_b
            ;;
        full)
            subsystem_a
            subsystem_b
            subsystem_c
            ;;
    esac
}
Coding Round
95. Composite pattern

Implement composite pattern for tree structures.

  • Leaf: leaf() { echo "Leaf $1: Operation"; }
  • Composite: composite() { echo "Composite $1: Operation"; for child in "{@:2}"; do eval "$child"; done; }
  • Add: add_child() { ... }
  • Count: count_leaves() { ... }
bash
#!/bin/bash
# Composite pattern
leaf() {
    local name=$1
    echo "Leaf $name: Operation"
}

composite() {
    local name=$1
    shift
    local children=("$@")
    echo "Composite $name: Operation"
    for child in "${children[@]}"; do
        eval "$child"
    done
}

# Usage
leaf1="leaf A"
leaf2="leaf B"
leaf3="leaf C"
leaf4="leaf D"

composite1="composite Comp1 $leaf1 $leaf2"
composite2="composite Comp2 $leaf3 $composite1"
root="composite Root $leaf4 $composite2"

eval "$root"

# Composite with count
count_leaves() {
    local name=$1
    shift
    local children=("$@")
    local count=0
    for child in "${children[@]}"; do
        if [[ "$child" == leaf* ]]; then
            count=$((count + 1))
        else
            local sub_count=$(eval "$child; echo $?")
            count=$((count + sub_count))
        fi
    done
    echo $count
}
Coding Round
96. Visitor pattern

Implement visitor pattern for adding operations to objects.

  • Visitor: concrete_visitor() { case $element in A*|B*) ... }
  • Elements: element_a() { echo "ElementA: $data"; }
  • Accept: concrete_visitor "$element"
  • Counting: counting_visitor() { ... }
bash
#!/bin/bash
# Visitor pattern
element_a() {
    local data=$1
    echo "ElementA: $data"
}

element_b() {
    local data=$1
    echo "ElementB: $data"
}

concrete_visitor() {
    local element=$1
    case $element in
        A*) element_a "${element#A:}";;
        B*) element_b "${element#B:}";;
    esac
}

counting_visitor() {
    local element=$1
    local count_a=$2
    local count_b=$3
    case $element in
        A*)
            count_a=$((count_a + 1))
            echo "Visiting ElementA ($count_a): ${element#A:}"
            ;;
        B*)
            count_b=$((count_b + 1))
            echo "Visiting ElementB ($count_b): ${element#B:}"
            ;;
    esac
    echo "$count_a:$count_b"
}

extended_visitor() {
    local element=$1
    case $element in
        A*) echo "Extended: ${element#A:} (A)";;
        B*) echo "Extended: ${element#B:} (B)";;
    esac
}

# Usage
elements=("A:Hello" "B:World" "A:Shell" "B:Visitor")

echo "Using standard visitor:"
for el in "${elements[@]}"; do
    concrete_visitor "$el"
done

echo "Using counting visitor:"
count_a=0
count_b=0
for el in "${elements[@]}"; do
    result=$(counting_visitor "$el" "$count_a" "$count_b")
    count_a=$(echo "$result" | cut -d: -f1)
    count_b=$(echo "$result" | cut -d: -f2)
done
echo "Counts: A=$count_a, B=$count_b"

echo "Using extended visitor:"
for el in "${elements[@]}"; do
    extended_visitor "$el"
done
Coding Round
97. Iterator pattern

Implement iterator pattern for sequential access.

  • Iterator:create_iterator() { iterator_collection=("$@"); iterator_position=0; }
  • Has next:has_next() { [ $iterator_position -lt ${#iterator_collection[@]} ]; }
  • Next:next() { ... }
  • Reverse:reverse_iterator() { for ((i=${#collection[@]}-1; i>=0; i--)); do ... }
bash
#!/bin/bash
# Iterator pattern
declare -a iterator_collection
iterator_position=0

create_iterator() {
    local collection=("$@")
    iterator_collection=("${collection[@]}")
    iterator_position=0
}

has_next() {
    [ $iterator_position -lt ${#iterator_collection[@]} ]
}

next() {
    if has_next; then
        local item=${iterator_collection[$iterator_position]}
        iterator_position=$((iterator_position + 1))
        echo "$item"
    fi
}

reverse_iterator() {
    local collection=("$@")
    for ((i=${#collection[@]}-1; i>=0; i--)); do
        echo "${collection[$i]}"
    done
}

filtered_iterator() {
    local collection=("$@")
    local predicate=$1
    shift
    for item in "$@"; do
        if $predicate "$item"; then
            echo "$item"
        fi
    done
}

skip_iterator() {
    local n=$1
    shift
    local collection=("$@")
    for ((i=n; i<${#collection[@]}; i++)); do
        echo "${collection[$i]}"
    done
}

# Usage
collection=("A" "B" "C" "D" "E")
create_iterator "${collection[@]}"
echo "Forward iteration:"
while has_next; do
    echo "$(next)"
done

echo "Reverse iteration:"
reverse_iterator "${collection[@]}"

echo "Filtered iteration (length <= 1):"
filtered_iterator "test" "${collection[@]}"

echo "Skip 2:"
skip_iterator 2 "${collection[@]}"
Coding Round
98. Template Method pattern

Implement template method with customizable steps.

  • Template: template_method() { step1; step2; step3; }
  • Default: default_template() { step1() { echo "Step 1"; }; ... }
  • Logging: logging_template() { step1() { echo "Logging: Step 1"; }; ... }
  • Data: data_template() { ... }
bash
#!/bin/bash
# Template Method pattern
template_method() {
    step1
    step2
    step3
}

default_template() {
    step1() { echo "Step 1"; }
    step2() { echo "Step 2"; }
    step3() { echo "Step 3"; }
    template_method
}

logging_template() {
    step1() { echo "Logging: Step 1"; }
    step2() { echo "Logging: Step 2"; }
    step3() { echo "Logging: Step 3"; }
    template_method
}

data_template() {
    local data=$1
    step1() { echo "Processing data: $data - Step 1"; }
    step2() { echo "Processing data: $data - Step 2"; }
    step3() { echo "Processing data: $data - Step 3"; }
    template_method
}

# Usage
echo "Using default template:"
default_template

echo "Using logging template:"
logging_template

echo "Using data processing template:"
data_template "example"
Coding Round
99. Builder pattern

Implement builder pattern for constructing complex objects.

  • Product: product_parts=()
  • Builder: build_step_a() { product_parts+=("Part A"); }
  • Director: build_minimal() { create_product; build_step_a; }
  • Custom: build_custom() { for step in "$@"; do case $step in ... }
bash
#!/bin/bash
# Builder pattern
declare -a product_parts

create_product() {
    product_parts=()
}

add_part() {
    product_parts+=("$1")
}

list_parts() {
    echo "${product_parts[@]}"
}

builder() {
    create_product
    build_step_a() { add_part "Part A"; }
    build_step_b() { add_part "Part B"; }
    build_step_c() { add_part "Part C"; }
    get_result() { echo "${product_parts[@]}"; }
}

director() {
    build_minimal() {
        create_product
        build_step_a
    }
    build_full() {
        create_product
        build_step_a
        build_step_b
        build_step_c
    }
    build_custom() {
        create_product
        for step in "$@"; do
            case $step in
                A) build_step_a;;
                B) build_step_b;;
                C) build_step_c;;
            esac
        done
    }
}

# Usage
echo "Minimal product:"
build_minimal
list_parts

echo "Full product:"
build_full
list_parts

echo "Custom product:"
create_product
build_step_c
build_step_a
list_parts

echo "Director custom:"
build_custom C A B
list_parts
Coding Round
100. Prototype pattern

Implement prototype pattern for cloning objects.

  • Prototype: prototype() { echo "$1"; }
  • Clone: clone_prototype() { echo "$1"; }
  • Deep clone: deep_clone() { echo "$1"; }
  • Mutable: set_mutable_data() { eval "$1='$2'"; }
bash
#!/bin/bash
# Prototype pattern
prototype() {
    local data=$1
    echo "$data"
}

clone_prototype() {
    local data=$1
    echo "$data"
}

deep_clone() {
    local data=$1
    echo "$data"
}

mutable_prototype() {
    local data=$1
    echo "$data"
}

set_mutable_data() {
    local name=$1
    local data=$2
    eval "$name='$data'"
}

get_mutable_data() {
    local name=$1
    eval "echo $$name"
}

# Usage
original="Original"
copy=$(clone_prototype "$original")
deep=$(deep_clone "$original")

echo "Original: $original"
echo "Copy: $copy"
echo "Deep copy: $deep"

mutable="Mutable"
set_mutable_data mutable_data "Original data"
echo "Original data: $(get_mutable_data mutable_data)"

set_mutable_data mutable_data "Modified data"
echo "Modified data: $(get_mutable_data mutable_data)"

cloned_mutable=$(clone_prototype "$mutable")
echo "Clone data: $cloned_mutable"

# Prototype with cache
declare -A prototype_cache

cached_prototype() {
    local data=$1
    if [ -z "${prototype_cache[$data]}" ]; then
        prototype_cache[$data]="cached_$data"
    fi
    echo "${prototype_cache[$data]}"
}