InterviewPitch
Julia interview questions

Julia Interview Questions with Answers

Most Asked Julia Interview Questions for Data Science and Engineering Roles

100+ QuestionsDetailed AnswersCode ExamplesUpdated for 2026

Introduction

Julia is a high‑performance, dynamic language for technical computing that combines the ease of Python with the speed of C. This page compiles the most frequently asked Julia interview questions – from basic syntax and multiple dispatch to advanced metaprogramming, parallel computing, and interfacing with C/Python – essential for any data scientist, researcher, or software engineer.

Why Julia?

  • High performance – JIT compiled to native code
  • Multiple dispatch – generic programming at its best
  • Built‑for‑science – linear algebra, machine learning, plotting
  • Seamless interoperability with C, Python, and R
  • Dynamic and interactive – REPL and Jupyter friendly
  • Rapidly growing ecosystem and community

Most Asked Julia Interview Questions

Beginner
1. What is Julia?

Julia is a high-level, high-performance dynamic programming language designed for technical computing. It combines the ease of use of Python with the speed of C.

  • High-performance: Compiled to native code via JIT
  • Dynamic: Interactive and easy to use
  • Multiple dispatch: Functions can have multiple definitions
  • Designed for science: Linear algebra, machine learning, plotting
  • Interoperability: Call C, Python, R, and other languages
julia
# Hello World in Julia
println("Hello, World!")
Beginner
2. How to declare variables in Julia?

Variables in Julia are declared using the = operator. Julia is dynamically typed, so you don't need to specify the type explicitly.

  • Assignment: x = 10
  • Dynamic typing: Types are inferred at runtime
  • Constants: const PI = 3.14159
  • Global scope: Variables defined at top level
  • Local scope: Variables defined inside functions
julia
# Variables in Julia
x = 10          # Integer
y = 3.14        # Float
name = "Julia"  # String
is_active = true # Boolean

println(x)
println(y)
println(name)
println(is_active)
Beginner
3. What are the data types in Julia?

Julia has a rich set of data types organized in a hierarchy. The most common types include integers, floating-point numbers, strings, booleans, and composite types.

  • Integer: Int, Int8, UInt16
  • Floating-point: Float64, Float32
  • String: String
  • Boolean: Bool (true/false)
  • Symbol: :symbol_name
  • Tuple: Immutable ordered collection
  • Array: Mutable collection of elements
  • Dict: Key-value pairs
julia
# Data Types in Julia
# Integer types
a = 10          # Int (defaults to Int64)
b = Int8(127)   # Int8
c = UInt16(255) # Unsigned Int

# Floating point
d = 3.14        # Float64
e = Float32(2.5) # Float32

# String
f = "Hello Julia"

# Boolean
g = true
h = false

# Symbol
i = :symbol_name

# Tuple
j = (1, "hello", 3.14)

# Array
k = [1, 2, 3, 4, 5]

# Dictionary
l = Dict("name" => "Julia", "version" => 1.9)

println(typeof(a)) # Int64
println(typeof(b)) # Int8
Beginner
4. How to define functions in Julia?

Functions in Julia can be defined using the function keyword or using assignment syntax. Julia supports multiple dispatch, meaning functions can be defined for different argument types.

  • Function declaration: function name(args) ... end
  • One-liner: name(args) = expression
  • Anonymous functions: x -> x^2
  • Keyword arguments: function f(; kw="default")
  • Multiple dispatch: Define same function for different types
julia
# Functions in Julia
# Function declaration
function add(a, b)
    return a + b
end

# One-line function
subtract(a, b) = a - b

# Function with default parameters
function greet(name="Guest")
    return "Hello, $name!"
end

# Multiple dispatch
function area(shape::String, dimensions...)
    if shape == "circle"
        r = dimensions[1]
        return π * r^2
    elseif shape == "rectangle"
        w, h = dimensions
        return w * h
    end
end

# Anonymous function
square = x -> x^2
double = x -> 2x

# Function with keyword arguments
function create_person(name; age=0, city="Unknown")
    return (name=name, age=age, city=city)
end

println(add(5, 3))
println(subtract(10, 4))
println(greet("Alice"))
println(area("circle", 5))
println(square(4))
println(create_person("Alice", age=25, city="NYC"))
Beginner
5. What are arrays in Julia?

Arrays are mutable collections of elements in Julia. They can be 1D (vectors), 2D (matrices), or multi-dimensional. Arrays are 1-indexed and support element-wise operations.

  • Creation: [1, 2, 3] or zeros(3,3)
  • 1-indexed: First element is at index 1
  • Element-wise: Use dot operator (.)
  • Methods: push!, pop!, map, filter, reduce
  • Comprehensions: [x^2 for x in 1:10]
julia
# Arrays in Julia
arr = [1, 2, 3, 4, 5]

# Map - transform each element
doubled = map(x -> x * 2, arr)
println(doubled) # [2, 4, 6, 8, 10]

# Filter - select elements
evens = filter(x -> x % 2 == 0, arr)
println(evens) # [2, 4]

# Reduce - aggregate
sum = reduce(+, arr)
println(sum) # 15

# Comprehension
squares = [x^2 for x in 1:10]
println(squares)

# Push and pop
push!(arr, 6)
println(arr)
pop!(arr)
println(arr)

# Array operations
a = [1, 2, 3]
b = [4, 5, 6]
c = a .+ b  # Element-wise addition
println(c)
Beginner
6. What are dictionaries in Julia?

Dictionaries are key‑value pairs in Julia, similar to maps in other languages. They provide efficient lookup by key.

  • Creation: Dict("key" => "value")
  • Access: dict["key"]
  • Add/Update: dict["new_key"] = value
  • Keys and values: keys(dict), values(dict)
  • Comprehensions: Dict(i => i^2 for i in 1:5)
julia
# Dictionaries in Julia
# Create dictionary
person = Dict("name" => "Alice", "age" => 25, "city" => "NYC")

# Access values
println(person["name"])
println(person["age"])

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

# Get with default
city = get(person, "city", "Unknown")

# Keys and values
println(keys(person))
println(values(person))

# Iterate over dictionary
for (key, value) in person
    println("$key: $value")
end

# Delete key
delete!(person, "country")

# Check if key exists
println(haskey(person, "name"))

# Dict comprehension
squares = Dict(i => i^2 for i in 1:5)
println(squares)
Beginner
7. What are tuples in Julia?

Tuples are immutable ordered collections of values in Julia. They are useful for returning multiple values from functions.

  • Creation: (1, "hello", 3.14)
  • Access: tuple[1]
  • Named tuples: (name="Alice", age=25)
  • Unpacking: a, b, c = tuple
  • Concatenation: (t1..., t2...)
julia
# Tuples in Julia
# Create tuple
t = (1, "hello", 3.14, true)

# Access elements
println(t[1])
println(t[2])

# Named tuples
person = (name="Alice", age=25, city="NYC")
println(person.name)
println(person.age)

# Tuple unpacking
a, b, c = (10, 20, 30)
println(a, b, c)

# Function returning multiple values
function divide(a, b)
    return div(a, b), a % b
end
quotient, remainder = divide(10, 3)
println("Quotient: $quotient, Remainder: $remainder")

# Tuple concatenation
t1 = (1, 2, 3)
t2 = (4, 5, 6)
t3 = (t1..., t2...)
println(t3)
Beginner
8. What are control flow statements in Julia?

Julia provides standard control flow statements including conditionals, loops, and exception handling.

  • If-else: if condition ... end
  • Ternary: condition ? a : b
  • For loops: for i in 1:10 ... end
  • While loops: while condition ... end
  • Break/Continue: break, continue
julia
# Control Flow in Julia
# If-else statement
age = 25
if age < 18
    println("Minor")
elseif age < 65
    println("Adult")
else
    println("Senior")
end

# Ternary operator
status = age >= 18 ? "Adult" : "Minor"
println(status)

# For loop
for i in 1:5
    println(i)
end

# For loop with array
fruits = ["apple", "banana", "orange"]
for fruit in fruits
    println(fruit)
end

# While loop
i = 1
while i <= 5
    println(i)
    i += 1
end

# Break and continue
for i in 1:10
    if i == 6
        break
    end
    if i % 2 == 0
        continue
    end
    println(i)
end
Beginner
9. What are comprehensions in Julia?

Comprehensions are a concise way to create arrays from other arrays using a generator expression. They are similar to list comprehensions in Python.

  • Array comprehension: [x^2 for x in 1:10]
  • Filtering: [x for x in 1:20 if x % 2 == 0]
  • Nested comprehension: [(i, j) for i in 1:3, j in 1:3]
  • Dict comprehension: Dict(i => i^2 for i in 1:5)
  • Generator expression: Lazy evaluation with sum(x^2 for x in 1:100)
julia
# Comprehensions in Julia
# Array comprehension
squares = [x^2 for x in 1:10]
println(squares)

# Filter with comprehension
evens = [x for x in 1:20 if x % 2 == 0]
println(evens)

# Nested comprehension
matrix = [(i, j) for i in 1:3, j in 1:3]
println(matrix)

# Dict comprehension
square_dict = Dict(i => i^2 for i in 1:5)
println(square_dict)

# Generator expression (lazy)
sum_squares = sum(x^2 for x in 1:100)
println(sum_squares)

# Conditional comprehension
results = [if x % 2 == 0 "even" else "odd" end for x in 1:10]
println(results)
Beginner
10. How to work with strings in Julia?

Julia provides powerful string manipulation capabilities including interpolation, concatenation, and various utility functions.

  • Creation: "Hello"
  • Concatenation: "Hello" * " " * "World"
  • Interpolation: "Hello, $name"
  • Functions: length, uppercase, lowercase, replace
  • Split/Join: split, join
julia
# Strings in Julia
# String creation
str1 = "Hello"
str2 = "World"
str3 = """Multi-line
string"""

# String concatenation
greeting = str1 * " " * str2
println(greeting)

# String interpolation
name = "Julia"
version = 1.9
println("Welcome to $name version $version")

# String functions
text = "Hello, World!"
println(length(text))
println(uppercase(text))
println(lowercase(text))
println(replace(text, "World" => "Julia"))

# Substring
println(text[1:5])

# Split and join
words = split("Hello World Julia")
println(words)
joined = join(words, "-")
println(joined)

# String comparison
println("hello" == "hello")
println("hello" < "world")

# String formatting
println(Printf.@sprintf("Value: %.2f", 3.14159))
Beginner
11. What are modules in Julia?

Modules are used to organize and encapsulate code, preventing namespace pollution. They allow you to export specific functions and variables.

  • Definition: module MyModule ... end
  • Export: export function_name
  • Import: using .MyModule
  • Private: Functions not exported are private
  • Inclusion: include("file.jl")
julia
# Modules in Julia
# Defining a module
module MyMath
    export add, subtract, PI

    const PI = 3.14159

    function add(a, b)
        return a + b
    end

    function subtract(a, b)
        return a - b
    end

    # Private function (not exported)
    function multiply(a, b)
        return a * b
    end
end

# Using a module
using .MyMath

println(add(5, 3))
println(subtract(10, 4))
println(MyMath.PI)
# println(MyMath.multiply(2, 3)) # Error: not exported

# Import specific functions
import .MyMath: PI
println(PI)

# Including external files
# include("math_functions.jl")
Intermediate
12. What are types in Julia?

Julia's type system is robust and supports abstract types, concrete types, and parametric types. Types enable multiple dispatch and performance optimization.

  • Abstract types: abstract type Animal end
  • Concrete types: struct Dog <: Animal ... end
  • Mutable types: mutable struct Person ... end
  • Parametric types: struct Point{T} ... end
  • Type hierarchy: Types can inherit from abstract types
julia
# Types in Julia
# Abstract type
abstract type Animal end

# Concrete type
struct Dog <: Animal
    name::String
    age::Int
end

# Mutable struct
mutable struct Person
    name::String
    age::Int
    city::String
end

# Constructor
function Person(name::String, age::Int)
    return Person(name, age, "Unknown")
end

# Type parameters
struct Point{T}
    x::T
    y::T
end

# Usage
dog = Dog("Rex", 3)
person = Person("Alice", 25)
p1 = Point(1.0, 2.0)
p2 = Point(1, 2)

# Field access
println(dog.name)
println(person.age)

# Type inheritance
abstract type Vehicle end
struct Car <: Vehicle
    make::String
    model::String
end
struct Bike <: Vehicle
    brand::String
end
Intermediate
13. What is multiple dispatch in Julia?

Multiple dispatch is a core feature of Julia where the function to call is determined by the types of all arguments, not just the first one.

  • Definition: Define same function for different types
  • Resolution: Most specific method is called
  • Performance: Enables type-specific optimizations
  • Example: function area(shape::Circle)
  • Benefits: Code organization, reusability, and performance
julia
# Multiple Dispatch in Julia
# Define functions with different signatures
function describe(x::Int)
    return "Integer: $x"
end

function describe(x::Float64)
    return "Float: $x"
end

function describe(x::String)
    return "String: $x"
end

# More specific types
function describe(x::Array{Int64,1})
    return "Array of Ints: $x"
end

# Abstract type dispatch
abstract type Shape end
struct Circle <: Shape
    radius::Float64
end
struct Rectangle <: Shape
    width::Float64
    height::Float64
end

function area(shape::Circle)
    return π * shape.radius^2
end

function area(shape::Rectangle)
    return shape.width * shape.height
end

# Usage
println(describe(42))
println(describe(3.14))
println(describe("Hello"))
println(describe([1, 2, 3]))

circle = Circle(5.0)
rectangle = Rectangle(4.0, 6.0)
println(area(circle))
println(area(rectangle))
Intermediate
14. How to handle exceptions in Julia?

Julia provides try-catch-finally blocks for error handling, similar to other languages. You can also throw custom errors.

  • Try-catch: try ... catch e ... end
  • Finally: try ... finally ... end
  • Throw: throw(DomainError("message"))
  • Error types: BoundsError, DomainError, MethodError
  • Check type: isa(e, BoundsError)
julia
# Exceptions and Errors in Julia
# Try-catch block
try
    # Code that might error
    result = 10 / 0
    println(result)
catch e
    println("Error caught: $e")
end

# Specific error handling
try
    arr = [1, 2, 3]
    println(arr[10])
catch e
    if isa(e, BoundsError)
        println("Index out of bounds!")
    else
        println("Other error: $e")
    end
end

# Finally block
try
    file = open("data.txt", "r")
    # Process file
    println("File opened successfully")
catch
    println("Error opening file")
finally
    println("Cleanup performed")
end

# Throwing errors
function divide(a, b)
    if b == 0
        throw(DomainError("Cannot divide by zero"))
    end
    return a / b
end

# Using error
try
    println(divide(10, 0))
catch e
    println("Error: $e")
end
Intermediate
15. How to work with files in Julia?

Julia provides functions for reading and writing files, including line-by-line reading and CSV handling.

  • Read file: open("file.txt", "r") do file ... end
  • Write file: open("file.txt", "w") do file ... end
  • Line by line: eachline(file)
  • CSV: Use CSV.read and CSV.write
  • File operations: readdir, isfile, isdir
julia
# File I/O in Julia
# Reading files
try
    open("example.txt", "r") do file
        content = read(file, String)
        println(content)
    end
catch
    println("File not found")
end

# Reading line by line
try
    open("data.txt", "r") do file
        for line in eachline(file)
            println(line)
        end
    end
catch
    println("Error reading file")
end

# Writing files
open("output.txt", "w") do file
    write(file, "Hello, World!
")
    write(file, "This is line 2
")
end

# Appending to files
open("output.txt", "a") do file
    write(file, "Appended line
")
end

# Reading CSV
using CSV
# data = CSV.read("data.csv", DataFrame)

# Writing CSV
# CSV.write("output.csv", data)
Intermediate
16. How to use packages in Julia?

Julia uses the built-in package manager Pkg for managing packages. You can add, update, and remove packages using Pkg commands.

  • Add: Pkg.add("PackageName")
  • Using: using PackageName
  • Status: Pkg.status()
  • Update: Pkg.update()
  • Remove: Pkg.rm("PackageName")
julia
# Packages in Julia
# Using Pkg
using Pkg

# Add package
# Pkg.add("Plots")
# Pkg.add("DataFrames")
# Pkg.add("CSV")

# Using packages
using Plots
using DataFrames
using CSV

# Check installed packages
# Pkg.status()

# Update packages
# Pkg.update()

# Remove package
# Pkg.rm("SomePackage")

# Environment management
# Pkg.activate("myenv")
# Pkg.add("HTTP")

# Using package in code
# using HTTP
# response = HTTP.get("https://example.com")
# println(response.body)
Intermediate
17. How to create plots in Julia?

Julia's Plots.jl package provides a unified interface for plotting. You can create various types of plots including line plots, scatter plots, and histograms.

  • Load: using Plots
  • Line plot: plot(x, y)
  • Scatter: scatter(x, y)
  • Histogram: histogram(data)
  • 3D plot: surface(x, y, z)
julia
# Plotting in Julia
using Plots

# Simple plot
x = 1:10
y = x.^2
plot(x, y, title="Square Function", label="x²")
# savefig("plot.png")

# Multiple series
y2 = 2x .+ 1
plot(x, y, label="x²")
plot!(x, y2, label="2x+1")

# Scatter plot
scatter(x, y, title="Scatter Plot")

# Histogram
data = randn(1000)
histogram(data, bins=30, title="Histogram")

# 3D plot
x = 1:10
y = 1:10
z = [i^2 + j^2 for i in x, j in y]
surface(x, y, z, title="3D Surface")

# Subplots
plot(x, y, label="Line")
scatter!(x, y2, label="Scatter")
# plotly() # Switch to interactive backend
Intermediate
18. How to work with DataFrames in Julia?

DataFrames.jl provides tabular data structures similar to pandas in Python. It offers various operations for data manipulation and analysis.

  • Create: DataFrame(Name=["Alice"], Age=[25])
  • Access columns: df.Name or df[:, "Name"]
  • Add column: df.NewCol = values
  • Filter: filter(row -> row.Age > 30, df)
  • Group by: groupby(df, :City)
julia
# DataFrames in Julia
using DataFrames

# Create DataFrame
df = DataFrame(
    Name=["Alice", "Bob", "Charlie", "David"],
    Age=[25, 30, 35, 40],
    City=["NYC", "LA", "Chicago", "Boston"]
)
println(df)

# Access columns
println(df.Name)
println(df[:, "Age"])
println(df[!, :City])

# Select rows
println(df[1:2, :])
println(df[df.Age .> 30, :])

# Add column
df.Salary = [50000, 60000, 70000, 80000]
println(df)

# Modify column
df.Age = df.Age .+ 1

# Sort DataFrame
sorted_df = sort(df, :Age)
println(sorted_df)

# Group and aggregate
using Statistics
grouped = groupby(df, :City)
mean_ages = combine(grouped, :Age => mean => :MeanAge)
println(mean_ages)

# Filter
filtered = filter(row -> row.Age > 30, df)
println(filtered)
Intermediate
19. How to do statistics in Julia?

Julia's Statistics module provides functions for statistical analysis including mean, median, standard deviation, and correlation.

  • Mean: mean(data)
  • Median: median(data)
  • Std: std(data)
  • Correlation: cor(x, y)
  • Quantiles: quantile(data, [0.25, 0.5, 0.75])
julia
# Statistics in Julia
using Statistics

# Basic statistics
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
println(mean(data))
println(median(data))
println(std(data))
println(var(data))

# Random data
using Random
random_data = randn(1000)
println(mean(random_data))
println(std(random_data))

# Correlation
x = 1:100
y = 2x .+ randn(100)
println(cor(x, y))

# Quantiles
println(quantile(data, [0.25, 0.5, 0.75]))

# Summary statistics
summary(data)

# Statistical tests
# using HypothesisTests
# ttest(data, 5.5)
Intermediate
20. How to do linear algebra in Julia?

Julia's LinearAlgebra module provides comprehensive linear algebra operations including matrix multiplication, decomposition, and eigenvalue computation.

  • Matrix multiplication: A * b
  • Solve system: A \ b
  • Eigenvalues: eigvals(A)
  • Determinant: det(A)
  • Inverse: inv(A)
julia
# Linear Algebra in Julia
using LinearAlgebra

# Vectors and matrices
A = [1 2 3; 4 5 6; 7 8 10]
b = [1, 2, 3]

# Matrix operations
println(A * b)
println(A' * A)  # Transpose

# Solving linear systems
x = A  b
println(x)

# Matrix decomposition
LU = lu(A)
println(LU)

# Eigenvalues
eigenvalues = eigvals(A)
println(eigenvalues)

# Determinant and inverse
println(det(A))
println(inv(A))

# Identity matrix
I = Matrix{Float64}(I, 3, 3)
println(I)

# Special matrices
zeros_matrix = zeros(3, 3)
ones_matrix = ones(3, 3)
println(zeros_matrix)
println(ones_matrix)
Intermediate
21. How to work with dates in Julia?

Julia's Dates module provides comprehensive date and time handling functionality.

  • Current date: now()
  • Create date: Date(2024, 1, 1)
  • Date arithmetic: date + Day(10)
  • Date difference: now() - date
  • Formatting: DateTime("2024-01-01", dateformat"yyyy-mm-dd")
julia
# Dates and Time in Julia
using Dates

# Current date and time
now = now()
println(now)

# Date creation
date1 = Date(2024, 1, 1)
date2 = DateTime(2024, 1, 1, 12, 0, 0)
println(date1)
println(date2)

# Date arithmetic
println(date1 + Day(10))
println(date1 + Month(2))
println(date2 + Hour(3))

# Date difference
diff = now() - date2
println(diff)

# Formatting dates
println(DateTime("2024-01-01", dateformat"yyyy-mm-dd"))
println(DateTime("2024-01-01T12:00:00"))

# Date functions
println(year(now()))
println(month(now()))
println(day(now()))
println(dayofweek(now()))
println(dayname(now()))

# Date range
dates = Date(2024, 1, 1):Day(1):Date(2024, 1, 10)
for d in dates
    println(d)
end
Intermediate
22. How to use regular expressions in Julia?

Julia supports regular expressions through the Regex module. You can match, replace, and search using regex patterns.

  • Create regex: r"hello"
  • Match: match(r"hello", text)
  • Find all: collect(eachmatch(r"hello", text))
  • Capture groups: r"(\d{4})-(\d{2})-(\d{2})"
  • Replace: replace(text, r"\d+" => "NUM")
julia
# Regular Expressions in Julia
using Regex

# Create regex
re = r"hello"
text = "hello world"

# Match
match_result = match(re, text)
println(match_result)

# Find all
text2 = "hello world hello again"
matches = collect(eachmatch(r"hello", text2))
println(length(matches))

# Regex with capture groups
re2 = r"(d{4})-(d{2})-(d{2})"
text3 = "Date: 2024-01-01"
match2 = match(re2, text3)
if match2 !== nothing
    println(match2[1]) # year
    println(match2[2]) # month
    println(match2[3]) # day
end

# Replace with regex
replaced = replace("Hello 123 World", r"d+" => "NUM")
println(replaced)

# Case insensitive
re3 = r"hello"i
println(match(re3, "HELLO world"))

# Regex compilation
re4 = Regex("^\d{3}-\d{4}$")
println(match(re4, "123-4567") !== nothing)
Advanced
23. How to do parallel computing in Julia?

Julia provides built-in support for parallel computing through multiple paradigms including distributed computing, threading, and GPU computing.

  • Add workers: addprocs(4)
  • Parallel map: @distributed for i in 1:100
  • Asynchronous: @spawn
  • Shared arrays: SharedArray{Int}(100)
  • Threading: @threads for i in 1:100
julia
# Parallel Computing in Julia
using Distributed

# Add workers
# addprocs(4)

# Parallel map
@everywhere function f(x)
    return x^2
end

# Parallel for loop
# @sync @distributed for i in 1:100
#     println("Processing: $i")
# end

# @spawn for asynchronous tasks
task = @spawn begin
    sleep(2)
    return "Task completed"
end
# result = fetch(task)
# println(result)

# Shared arrays
using SharedArrays
shared_arr = SharedArray{Int}(100)

# Parallel reduction
# using Distributed
# sum = @sync @distributed (+) for i in 1:1000
#     i^2
# end

# Threading
using Base.Threads
@threads for i in 1:100
    println("Thread $tid: $i")
end

# Atomic operations
using Base.Atomics
counter = Atomic{Int}(0)
for i in 1:100
    @spawn atomic_add!(counter, 1)
end
Advanced
24. What is metaprogramming in Julia?

Metaprogramming in Julia allows you to write code that generates other code. This includes macros, expressions, and code generation techniques.

  • Expressions: ex = :(2 + 3)
  • Macros: macro name(expr) ... end
  • Quote: quote ... end
  • Interpolation: :\$x + 3
  • Generate functions: @generated function
julia
# Metaprogramming in Julia
# Expressions
ex = :(2 + 3)
println(eval(ex))

# Quote
ex2 = quote
    x = 10
    y = 20
    x + y
end
println(eval(ex2))

# Macro definition
macro sayhello()
    return :(println("Hello, World!"))
end

# Macro with arguments
macro greet(name)
    return :(println("Hello, $name!"))
end

# Using macros
@sayhello()
@greet("Julia")

# Interpolate in expressions
x = 5
ex3 = :($x + 3)
println(eval(ex3))

# Generate functions
function generate_expr(n)
    return :(println("Number: $n"))
end

# String macro
x = 42
println(meta_parse("x + 1"))
Advanced
25. How to interface with C in Julia?

Julia can call C functions directly using the ccall function. This provides high performance and access to existing C libraries.

  • ccall:ccall((:function_name, lib), return_type, (arg_types,), args)
  • Load library:Libdl.dlopen("lib.so")
  • C structs:mutable struct Point ... end
  • Memory management:Libc.malloc and Libc.free
  • C strings:unsafe_convert(Ptr{UInt8}, str)
julia
# Interoperability with C in Julia
# Calling C functions
# using Libdl

# # Load C library
# lib = dlopen("libm.so.6")

# # Define function
# function c_sin(x::Float64)
#     return ccall(
#         (:sin, lib),
#         Float64,
#         (Float64,),
#         x
#     )
# end

# # Call C function
# println(c_sin(0.5))

# # C structs
# mutable struct Point
#     x::Cfloat
#     y::Cfloat
# end

# # C pointers
# function allocate_buffer(n::Int)
#     return Libc.malloc(n * sizeof(Int))
# end

# function free_buffer(ptr)
#     Libc.free(ptr)
# end

# # C string handling
# c_string = Base.unsafe_convert(Ptr{UInt8}, "Hello")
# println(c_string)
Advanced
26. How to optimize performance in Julia?

Julia provides several techniques for performance optimization including type stability, preallocation, and compiler annotations.

  • Type annotations:function f(x::Float64)
  • Constants:const GLOBAL = 10.0
  • @code_warntype: Check type stability
  • Preallocate:Vector{Float64}(undef, n)
  • @inbounds: Disable bounds checking
julia
# Performance Optimization in Julia
# Performance tips

# 1. Use type annotations
function sum_array(A::Vector{Float64})
    s = 0.0
    for x in A
        s += x
    end
    return s
end

# 2. Avoid global variables
const GLOBAL_CONST = 10.0
function use_global()
    return GLOBAL_CONST * 2
end

# 3. Use @code_warntype to check type stability
# @code_warntype sum_array([1.0, 2.0, 3.0])

# 4. Preallocate arrays
function preallocate()
    arr = Vector{Float64}(undef, 1000)
    for i in 1:1000
        arr[i] = i^2
    end
    return arr
end

# 5. Use @inbounds for bounds checking
function sum_inbounds(A)
    s = 0.0
    @inbounds for i in eachindex(A)
        s += A[i]
    end
    return s
end

# 6. Use @fastmath for aggressive optimizations
function fast_sum(A)
    s = 0.0
    @fastmath for x in A
        s += x
    end
    return s
end

# 7. Avoid dynamic dispatch
function process(x::Float64)
    return x * 2
end

# 8. Use views for slicing
view(arr, 1:10)
Advanced
27. How to do networking in Julia?

Julia provides networking capabilities through HTTP clients, servers, and WebSockets. The HTTP.jl package is commonly used for web communication.

  • HTTP client: HTTP.get("https://api.github.com")
  • HTTP server: HTTP.serve(request_handler, "127.0.0.1", 8080)
  • WebSockets: WebSockets.serve("127.0.0.1", 8080) do ws
  • TCP client: connect("example.com", 80)
  • TCP server: listen(8080)
julia
# Networking in Julia
using Sockets

# HTTP client
using HTTP
# response = HTTP.get("https://api.github.com")
# println(String(response.body))

# HTTP server
# using HTTP
# function request_handler(req::HTTP.Request)
#     return HTTP.Response(200, "Hello, World!")
# end
# HTTP.serve(request_handler, "127.0.0.1", 8080)

# WebSockets
# using WebSockets
# WebSockets.serve("127.0.0.1", 8080) do ws
#     while true
#         msg = read(ws, String)
#         write(ws, "Echo: $msg")
#     end
# end

# TCP client
# sock = connect("example.com", 80)
# write(sock, "GET / HTTP/1.1
Host: example.com

")
# response = read(sock, String)
# println(response)
# close(sock)

# TCP server
# server = listen(8080)
# while true
#     sock = accept(server)
#     @async begin
#         write(sock, "Hello from server!
")
#         close(sock)
#     end
# end
Advanced
28. How to work with JSON in Julia?

The JSON.jl package provides functions for encoding and decoding JSON data, which is useful for API communication and data exchange.

  • Encode: JSON.json(data)
  • Pretty print: JSON.json(data, 2)
  • Decode: JSON.parse(json_string)
  • Read file: JSON.parsefile("data.json")
  • Nested structures: Handles complex nested data
julia
# Working with JSON in Julia
using JSON

# Encode to JSON
data = Dict(
    "name" => "Alice",
    "age" => 25,
    "city" => "NYC",
    "hobbies" => ["reading", "coding"]
)
json_string = JSON.json(data)
println(json_string)

# Pretty print
pretty_json = JSON.json(data, 2)
println(pretty_json)

# Decode from JSON
json_str = "{"name":"Bob","age":30,"city":"LA"}"
parsed = JSON.parse(json_str)
println(parsed["name"])
println(parsed["age"])

# Working with arrays
json_array = JSON.json([1, 2, 3, 4, 5])
println(json_array)
parsed_array = JSON.parse(json_array)
println(parsed_array)

# Nested structures
nested = Dict(
    "user" => Dict(
        "id" => 1,
        "profile" => Dict(
            "name" => "Alice",
            "email" => "alice@example.com"
        )
    )
)
println(JSON.json(nested, 2))

# Read JSON from file
# data = JSON.parsefile("data.json")
Advanced
29. How to test code in Julia?

Julia's Test module provides testing capabilities including assertions, test sets, and benchmarking tools.

  • Basic test: @test 1 + 1 == 2
  • Test sets: @testset "Description" begin ... end
  • Floating point: @test 0.1 + 0.2 ≈ 0.3
  • Throws: @test_throws DomainError sqrt(-1)
  • Benchmarking: @benchmark sum(1:1000)
julia
# Testing in Julia
using Test

# Basic tests
@test 1 + 1 == 2
@test 2 * 3 == 6

# Test with floating point
@test 0.1 + 0.2 ≈ 0.3

# Test macros
@testset "Math operations" begin
    @test 2 + 2 == 4
    @test 3 * 3 == 9
    @test 10 / 2 == 5
end

# Nested test sets
@testset "Advanced tests" begin
    @testset "Trigonometry" begin
        @test sin(0) == 0
        @test cos(0) == 1
    end
    @testset "Logarithms" begin
        @test log(1) == 0
        @test exp(1) == ℯ
    end
end

# Test with throws
@test_throws DomainError sqrt(-1)

# Test failure
# @test 1 == 2

# Benchmarking
using BenchmarkTools
# @benchmark sum(1:1000)

# Property-based testing
# using PropCheck
# @check for x in integers(1:10)
#     x + 1 > x
# end
Advanced
30. How to debug in Julia?

Julia provides various debugging tools including logging, @show, interactive debuggers, and stack traces.

  • @show: @show x + y
  • Logging: @info, @warn, @error
  • Debugger: @enter function(args)
  • Stack trace: showerror(stdout, e, catch_backtrace())
  • Breakpoints: breakpoint function_name
julia
# Debugging in Julia
# Using @show macro
x = 10
y = 20
@show x + y

# Using @debug for debugging messages
@debug "Debug message" x y

# Using @warn for warnings
@warn "This is a warning" x y

# Using @info for informational messages
@info "Processing data" size=100

# Using @error for error messages
@error "Something went wrong" error="Division by zero"

# Interactive debugging
# using Debugger
# @enter function_to_debug(args)

# Stack trace
try
    error("Something went wrong")
catch e
    println("Stack trace:")
    showerror(stdout, e, catch_backtrace())
end

# Logging
using Logging
with_logger(ConsoleLogger()) do
    @info "This is an info message"
end

# Breakpoint debugging
# using Debugger
# breakpoint function_to_debug
Advanced
31. What are abstract types and interfaces in Julia?

Abstract types define type hierarchies and interfaces. They provide a way to organize types and define common behavior through multiple dispatch.

  • Abstract types: abstract type Animal end
  • Inheritance: struct Dog <: Animal
  • Interfaces: Define functions that work on abstract types
  • Type hierarchy: Mammal <: Animal
  • Interface functions: function make_sound(animal::Animal)
julia
# Abstract Types and Interfaces
# Abstract type hierarchy
abstract type Animal end
abstract type Mammal <: Animal end
abstract type Bird <: Animal end

# Concrete types
struct Dog <: Mammal
    name::String
    age::Int
end

struct Cat <: Mammal
    name::String
    age::Int
end

struct Sparrow <: Bird
    name::String
    wingspan::Float64
end

# Interface functions
function make_sound(animal::Animal)
    return "Some sound"
end

function make_sound(animal::Dog)
    return "Woof!"
end

function make_sound(animal::Cat)
    return "Meow!"
end

function make_sound(animal::Sparrow)
    return "Chirp!"
end

# Type hierarchy checking
dog = Dog("Rex", 3)
cat = Cat("Whiskers", 2)
sparrow = Sparrow("Tweet", 15.0)

println(make_sound(dog))
println(make_sound(cat))
println(make_sound(sparrow))

# Type checking
println(dog isa Animal)
println(dog isa Mammal)
println(dog isa Dog)
println(dog isa Cat)
Advanced
32. What are parameterized types in Julia?

Parameterized types allow you to define generic types that work with multiple type parameters. This enables type-safe generic programming.

  • Definition:struct Point{T} ... end
  • Usage:Point(1.0, 2.0)
  • Multiple parameters:struct Pair{A,B}
  • Type constraints:where {T<:Number}
  • Covariance: Supports type relationships
julia
# Parameterized Types
# Basic parameterized type
struct Point{T}
    x::T
    y::T
end

# Creating points
p1 = Point(1.0, 2.0)
p2 = Point(1, 2)
p3 = Point{Float64}(3.0, 4.0)

# Function with parameterized types
function distance(p1::Point{T}, p2::Point{T}) where {T<:Number}
    return sqrt((p1.x - p2.x)^2 + (p1.y - p2.y)^2)
end

# Multiple parameters
struct Pair{A,B}
    first::A
    second::B
end

# Covariance and contravariance
struct Container{T}
    value::T
end

# Type constraints
function process_value(x::T) where {T<:Number}
    return x * 2
end

# Generic functions
function get_first(x::Tuple)
    return x[1]
end

# Usage
println(distance(Point(0.0, 0.0), Point(3.0, 4.0)))
println(process_value(5))
println(process_value(3.14))
Advanced
33. How to write macros in Julia?

Macros in Julia are powerful tools for metaprogramming. They manipulate expressions before compilation, enabling domain-specific language creation.

  • Definition: macro name(expr) ... end
  • Usage: @name
  • String macros: macro uppercase_str(s)
  • Debug macros: @dbg expr
  • Code generation: Generate functions or expressions
julia
# Macros and Metaprogramming
# Basic macro
macro times_two(expr)
    return :(2 * $expr)
end

# Usage
@times_two 5

# Macro with arguments
macro pow(base, exp)
    return :($base ^ $exp)
end

@pow 2 3

# String macros
macro uppercase_str(s)
    return :(uppercase($s))
end

# Custom macro for debugging
macro dbg(expr)
    return quote
        println("Expression: $(string($expr))")
        println("Value: ", $expr)
    end
end

# Using debug macro
x = 10
@dbg x + 5

# Macro for creating functions
macro define_square(name)
    return quote
        function $(esc(name))(x)
            return x^2
        end
    end
end

@define_square square_func
println(square_func(5))

# Macro for custom syntax
macro repeat(n, expr)
    return quote
        for i in 1:$n
            $expr
        end
    end
end

@repeat 3 println("Hello")
Advanced
34. What are generators and coroutines in Julia?

Generators and coroutines in Julia provide ways to work with lazy sequences and cooperative multitasking. Tasks and Channels are key components.

  • Generators: Task(fibonacci_generator)
  • Channels: Channel() do ch ... end
  • Tasks: @async and @sync
  • Produce/Consume: produce, consume
  • Stateful functions: function counter() ... end
julia
# Generators and Coroutines
# Generator function
function fibonacci_generator()
    a, b = 0, 1
    while true
        produce(a)
        a, b = b, a + b
    end
end

# Using generator with Task
task = Task(fibonacci_generator)
for i in 1:10
    println(consume(task))
end

# Custom generator using Channel
function fibonacci_channel()
    Channel() do ch
        a, b = 0, 1
        while true
            put!(ch, a)
            a, b = b, a + b
        end
    end
end

# Using Channel
for n in take(fibonacci_channel(), 10)
    println(n)
end

# Coroutine with state
function counter(start=0)
    state = start
    return function()
        state += 1
        return state
    end
end

counter = counter()
println(counter())
println(counter())
println(counter())

# Async/await with tasks
function async_example()
    task = @async begin
        sleep(1)
        return "Done"
    end
    return fetch(task)
end
println(async_example())
Advanced
35. What are advanced array operations in Julia?

Julia provides advanced array operations including broadcasting, reshaping, and various linear algebra operations for scientific computing.

  • Broadcasting: A .+ 1
  • Reshaping: reshape(arr, 3, 3)
  • Matrix operations: A * B
  • Element-wise: A .* B
  • Linear algebra: norm, trace, diag
julia
# Advanced Array Operations
# Array initialization
A = zeros(3, 3)
B = ones(3, 3)
C = fill(5.0, 3, 3)
I = Matrix{Float64}(I, 3, 3)

# Reshaping
arr = 1:9
matrix = reshape(arr, 3, 3)
println(matrix)

# Transpose
println(matrix')

# Broadcasting
A = [1 2 3; 4 5 6; 7 8 9]
B = A .+ 1
C = A .* 2
D = A .^ 2

# Element-wise operations
println(B)
println(C)
println(D)

# Matrix multiplication
X = rand(3, 3)
Y = rand(3, 3)
Z = X * Y
println(Z)

# Element-wise multiplication
W = X .* Y
println(W)

# Linear algebra functions
using LinearAlgebra
norm_X = norm(X)
trace_X = trace(X)
diag_X = diag(X)
Advanced
36. How to handle missing data in Julia?

Julia's Missings.jl provides tools for working with missing values, including arrays with missing data and functions for handling them.

  • Missing values: [1, 2, missing, 4]
  • Check missing: ismissing.(data)
  • Remove missing: collect(skipmissing(data))
  • Replace missing: coalesce.(data, 0)
  • Skip missing: sum(skipmissing(data))
julia
# Working with Missing Data
using Missings

# Creating arrays with missing values
data = [1, 2, missing, 4, 5, missing, 7]
println(data)

# Check for missing values
println(ismissing.(data))
println(any(ismissing.(data)))

# Remove missing values
clean_data = collect(skipmissing(data))
println(clean_data)

# Replace missing values
replaced = coalesce.(data, 0)
println(replaced)

# Operations with missing values
x = [1, 2, missing, 4]
y = [5, 6, missing, 8]
z = x .+ y  # Results in [6, 8, missing, 12]
println(z)

# Ignoring missing values
sum_complete = sum(skipmissing(x))
println(sum_complete)

# Working with DataFrames
using DataFrames
df = DataFrame(
    A=[1, 2, 3, 4],
    B=[missing, 5, 6, missing],
    C=["x", missing, "z", "w"]
)
println(df)
println(describe(df))

# Drop missing rows
df_clean = dropmissing(df)
println(df_clean)
Advanced
37. How to do sorting and searching in Julia?

Julia provides built-in functions for sorting arrays and searching for elements. These operations are optimized for performance.

  • Sort: sort(arr)
  • In-place sort: sort!(arr)
  • Custom sort: sort(arr, by = x -> x[1])
  • Search: findall(x -> x > 5, arr)
  • Binary search: searchsorted(arr, 7)
julia
# Sorting and Searching
# Basic sorting
arr = [5, 2, 8, 1, 9, 3]
sort!(arr)
println(arr)

# Sorting without mutation
arr2 = [5, 2, 8, 1, 9, 3]
sorted = sort(arr2)
println(arr2)
println(sorted)

# Sorting with custom comparator
arr3 = [(5, "apple"), (3, "banana"), (8, "cherry")]
sort!(arr3, by = x -> x[1])
println(arr3)

# Sorting descending
arr4 = [5, 2, 8, 1, 9, 3]
sort!(arr4, rev=true)
println(arr4)

# Search functions
arr5 = [1, 3, 5, 7, 9, 11]
println(findall(x -> x > 5, arr5))
println(findfirst(x -> x > 5, arr5))
println(findlast(x -> x > 5, arr5))

# Binary search (requires sorted array)
idx = searchsorted(arr5, 7)
println(idx)

# Contains
println(7 in arr5)
println(4 in arr5)
Advanced
38. What are mathematical operations in Julia?

Julia supports a wide range of mathematical operations including basic arithmetic, special functions, and linear algebra. Many of these are built-in.

  • Basic arithmetic: +, -, *, /, ^
  • Trigonometric: sin, cos, tan
  • Special functions: gamma, beta, erf
  • Random numbers: rand, randn
  • Statistics: mean, std, cor
julia
# Mathematical Operations
# Basic arithmetic
x = 10
y = 3
println(x + y)
println(x - y)
println(x * y)
println(x / y)
println(x % y)
println(x ^ y)

# Mathematical functions
println(sin(π/4))
println(cos(π/4))
println(tan(π/4))
println(exp(1))
println(log(ℯ))
println(log10(100))
println(sqrt(9))

# Special functions
using SpecialFunctions
println(gamma(5))
println(beta(2, 3))
println(erf(1.0))

# Random numbers
using Random
Random.seed!(123)
println(rand())
println(randn())
println(rand(1:10))
println(rand(3, 3))

# Statistics
using Statistics
data = randn(1000)
println(mean(data))
println(std(data))
println(var(data))

# Linear algebra
using LinearAlgebra
A = rand(3, 3)
println(eigvals(A))
println(det(A))
Advanced
39. How to do data serialization in Julia?

Julia supports various data serialization formats including HDF5, JLD2, and BSON. These formats are useful for saving and loading data.

  • HDF5: h5open("data.h5", "w") do file
  • JLD2: @save "data.jld2" arr metadata
  • BSON: BSON.@save "data.bson" arr metadata
  • Read: read(file, "dataset")
  • Write: write(file, "dataset", data)
julia
# Data Serialization
# Using HDF5
using HDF5

# Write to HDF5
# h5open("data.h5", "w") do file
#     write(file, "dataset", rand(10, 10))
#     write(file, "metadata", Dict("name" => "experiment1"))
# end

# # Read from HDF5
# h5open("data.h5", "r") do file
#     data = read(file, "dataset")
#     metadata = read(file, "metadata")
#     println(data)
#     println(metadata)
# end

# Using JLD2
using JLD2

# Write to JLD2
# @save "data.jld2" arr metadata
# arr = 1:10
# metadata = Dict("version" => "1.0")
# @save "data.jld2" arr metadata

# # Read from JLD2
# @load "data.jld2" arr metadata
# println(arr)
# println(metadata)

# Using BSON
using BSON

# # Write to BSON
# BSON.@save "data.bson" arr metadata
# 
# # Read from BSON
# BSON.@load "data.bson" arr metadata
# println(arr)
# println(metadata)
Advanced
40. How to interface with Python in Julia?

PyCall.jl allows Julia to call Python libraries directly. This provides access to the extensive Python ecosystem from Julia.

  • Import: pyimport("numpy")
  • Use Python functions: np.sum(arr)
  • Create Python objects: np.array([1, 2, 3])
  • Plotting: pyimport("matplotlib.pyplot")
  • Conversion: pyconvert(Array, py_arr)
julia
# Interfacing with Python
using PyCall

# Import Python modules
np = pyimport("numpy")
plt = pyimport("matplotlib.pyplot")

# Using numpy arrays
arr = np.array([1, 2, 3, 4, 5])
println(arr)
println(np.sum(arr))
println(np.mean(arr))

# Creating arrays from Python
py_arr = np.random.randn(10, 10)
println(size(py_arr))

# Using matplotlib
x = np.linspace(0, 2π, 100)
y = np.sin(x)
# plt.plot(x, y)
# plt.show()

# Calling Python functions
math = pyimport("math")
println(math.sqrt(16))
println(math.factorial(5))

# Converting between Julia and Python
julia_arr = [1, 2, 3, 4]
py_arr2 = pyconvert(PyObject, julia_arr)
println(py_arr2)

# Working with pandas
pd = pyimport("pandas")
df = pd.DataFrame(Dict("col1" => [1, 2, 3], "col2" => ["a", "b", "c"]))
println(df)
Coding Round
41. Reverse a string

Reverse a string by converting it to a character array, reversing it, and joining it back together.

  • Method: join(reverse(collect(s)))
  • Alternative: Iterate in reverse
  • Performance: O(n) time complexity
  • Unicode: Works with Unicode strings
julia
# Reverse a string
function reverse_string(s::String)
    return join(reverse(collect(s)))
end
println(reverse_string("hello")) # "olleh"

# Alternative using iteration
function reverse_string_iter(s::String)
    chars = collect(s)
    reversed = [chars[i] for i in length(chars):-1:1]
    return join(reversed)
end
Coding Round
42. Check palindrome

Check if a string is a palindrome by comparing it to its reverse. The function should handle case sensitivity and whitespace.

  • Method: s == join(reverse(collect(s)))
  • Case insensitive: lowercase
  • In-place: Two-pointer comparison
  • Complexity: O(n) time, O(n) space
julia
# Check palindrome
function is_palindrome(s::String)
    cleaned = lowercase(strip(s))
    return cleaned == join(reverse(collect(cleaned)))
end
println(is_palindrome("racecar")) # true
println(is_palindrome("hello")) # false

# Without extra allocation
function is_palindrome_inplace(s::String)
    chars = collect(lowercase(s))
    i, j = 1, length(chars)
    while i < j
        if chars[i] != chars[j]
            return false
        end
        i += 1
        j -= 1
    end
    return true
end
Coding Round
43. Find max in array

Find the maximum value in an array using the built-in maximum function or by manual iteration.

  • Built-in: maximum(arr)
  • Manual: Iterate and track max
  • Empty array: Handle with isempty
  • Complexity: O(n) time
julia
# Find max in array
function find_max(arr)
    return maximum(arr)
end
println(find_max([1, 5, 3, 9, 2])) # 9

# Manual implementation
function find_max_manual(arr)
    max_val = arr[1]
    for x in arr
        if x > max_val
            max_val = x
        end
    end
    return max_val
end
Coding Round
44. Remove duplicates

Remove duplicate elements from an array using unique or Set. This preserves order in the result.

  • Built-in: unique(arr)
  • Set: collect(Set(arr))
  • Order: unique preserves order
  • Complexity: O(n) time
julia
# Remove duplicates
function remove_duplicates(arr)
    return unique(arr)
end
println(remove_duplicates([1, 2, 2, 3, 3, 4])) # [1, 2, 3, 4]

# Using Set
function remove_duplicates_set(arr)
    return collect(Set(arr))
end
Coding Round
45. Merge arrays

Merge two arrays using vcat or the spread operator. This creates a new array without modifying the originals.

  • vcat: vcat(arr1, arr2)
  • Spread: [arr1..., arr2...]
  • In-place: append!(arr1, arr2)
  • Unique merge: unique(vcat(arr1, arr2))
julia
# Merge arrays
function merge_arrays(arr1, arr2)
    return vcat(arr1, arr2)
end
println(merge_arrays([1, 2], [3, 4])) # [1, 2, 3, 4]

# Alternative with concatenation
function merge_concat(arr1, arr2)
    return [arr1..., arr2...]
end
Coding Round
46. Convert string to number

Convert a string to a number using parse or tryparse for safe conversion.

  • parse: parse(Float64, str)
  • Integer: parse(Int, str)
  • Tryparse: tryparse(Float64, str)
  • Error handling: Check for valid input
julia
# Convert string to number
function string_to_number(str::String)
    return parse(Float64, str)
end
println(string_to_number("42")) # 42.0

# Convert to integer
function string_to_int(str::String)
    return parse(Int, str)
end
println(string_to_int("42")) # 42
Coding Round
47. Loop through dictionary

Iterate through a dictionary's key-value pairs using a for loop. Access keys and values using destructuring.

  • For loop: for (key, value) in dict
  • Keys: keys(dict)
  • Values: values(dict)
  • Pair iteration: for pair in dict
julia
# Loop through dictionary
function loop_dict(dict)
    for (key, value) in dict
        println("$key => $value")
    end
end

data = Dict("name" => "Alice", "age" => 25, "city" => "NYC")
loop_dict(data)
Coding Round
48. Delay function execution

Delay function execution using sleep for blocking delays or @async for non-blocking delays.

  • Blocking: sleep(seconds)
  • Async: @async begin sleep(2); fn() end
  • Task: Create and fetch a task
  • Timer: Use Timer for periodic execution
julia
# Delay function execution
using Dates

function delayed_execution(delay_seconds, fn)
    sleep(delay_seconds)
    return fn()
end

# Example usage
result = delayed_execution(2, () -> println("After 2 seconds"))
println(result)

# Async version
function async_delay(delay_seconds, fn)
    @async begin
        sleep(delay_seconds)
        fn()
    end
end
Coding Round
49. HTTP GET request

Make an HTTP GET request using HTTP.jl. Handle errors and parse the response.

  • GET: HTTP.get(url)
  • Response: String(response.body)
  • POST: HTTP.post(url, headers, body)
  • Error handling: Try-catch for network errors
julia
# HTTP GET request
using HTTP

function fetch_data(url::String)
    try
        response = HTTP.get(url)
        return String(response.body)
    catch e
        println("Error: $e")
        return nothing
    end
end

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

# POST request
function post_data(url::String, data::Dict)
    try
        json_data = JSON.json(data)
        response = HTTP.post(url, 
            ["Content-Type" => "application/json"], 
            json_data)
        return String(response.body)
    catch e
        println("Error: $e")
        return nothing
    end
end
Coding Round
50. Create a promise-like task

Create a task that simulates a promise with asynchronous execution and result handling.

  • Task: @async
  • Fetch: fetch(task)
  • Error handling: Try-catch for task errors
  • Chaining: Combine multiple tasks
julia
# Create a promise-like task
function create_promise(should_resolve::Bool)
    return @async begin
        sleep(1)
        if should_resolve
            return "Success!"
        else
            error("Failed!")
        end
    end
end

# Using the promise
task = create_promise(true)
result = fetch(task)
println(result)

# With error handling
task2 = create_promise(false)
try
    result2 = fetch(task2)
    println(result2)
catch e
    println("Caught error: $e")
end
Coding Round
51. Factorial

Calculate factorial using recursion or iteration. Handle edge cases like 0 and negative numbers.

  • Recursive:n <= 1 ? 1 : n * factorial(n-1)
  • Iterative: Loop from 2 to n
  • Edge cases: 0! = 1, handle negatives
  • Performance: Iterative is faster
julia
# Factorial
function factorial(n::Int)
    if n <= 1
        return 1
    end
    return n * factorial(n-1)
end
println(factorial(5)) # 120

# Iterative version
function factorial_iterative(n::Int)
    result = 1
    for i in 2:n
        result *= i
    end
    return result
end
Coding Round
52. Fibonacci

Calculate Fibonacci numbers using recursion, iteration, or memoization. Handle base cases.

  • Recursive:n <= 1 ? n : fib(n-1) + fib(n-2)
  • Iterative: Loop with variables
  • Memoization: Cache results for performance
  • Complexity: O(2^n) recursive, O(n) iterative
julia
# Fibonacci
function fibonacci(n::Int)
    if n <= 1
        return n
    end
    return fibonacci(n-1) + fibonacci(n-2)
end
println(fibonacci(8)) # 21

# Iterative version
function fibonacci_iterative(n::Int)
    a, b = 0, 1
    for i in 2:n
        a, b = b, a + b
    end
    return n > 0 ? b : a
end
Coding Round
53. FizzBuzz

Print numbers from 1 to n, replacing multiples of 3 with "Fizz", multiples of 5 with "Buzz", and multiples of both with "FizzBuzz".

  • Logic: Check divisibility by 3 and 5
  • Order: Check 15 first, then 3, then 5
  • Output: Print each result
  • Use case: Common interview question
julia
# FizzBuzz
function fizzbuzz(n::Int)
    for i in 1:n
        if i % 15 == 0
            println("FizzBuzz")
        elseif i % 3 == 0
            println("Fizz")
        elseif i % 5 == 0
            println("Buzz")
        else
            println(i)
        end
    end
end
fizzbuzz(15)
Coding Round
54. Find missing number

Find the missing number in a consecutive sequence using the formula n*(n+1)/2 - sum.

  • Formula: n * (n + 1) ÷ 2 - sum(arr)
  • XOR: XOR all numbers and indices
  • Edge cases: Empty array, missing first or last
  • Complexity: O(n) time, O(1) space
julia
# Find missing number
function find_missing(arr)
    n = length(arr) + 1
    total = n * (n + 1) ÷ 2
    sum_arr = sum(arr)
    return total - sum_arr
end
println(find_missing([1, 2, 4, 5, 6])) # 3
Coding Round
55. Find duplicates

Find duplicate elements in an array using a Set to track seen elements. Collect duplicates into a set or array.

  • Set: Track seen elements
  • Filter:filter(x -> x in seen, arr)
  • Complexity: O(n) time
  • Returns: Set or array of duplicates
julia
# Find duplicates
function find_duplicates(arr)
    seen = Set()
    duplicates = Set()
    for x in arr
        if x in seen
            push!(duplicates, x)
        else
            push!(seen, x)
        end
    end
    return collect(duplicates)
end
println(find_duplicates([1, 2, 3, 2, 4, 3])) # [2, 3]
Coding Round
56. Sum of array

Calculate the sum of all elements in an array using sum or manual iteration.

  • Built-in: sum(arr)
  • Manual: reduce(+, arr)
  • For loop: Iterate and accumulate
  • Empty array: Returns 0
julia
# Sum of array
function sum_array(arr)
    return sum(arr)
end
println(sum_array([1, 2, 3, 4, 5])) # 15

# Manual implementation
function sum_array_manual(arr)
    s = 0
    for x in arr
        s += x
    end
    return s
end
Coding Round
57. Average of array

Calculate the average by dividing the sum by the length. Handle empty arrays.

  • Method: sum(arr) / length(arr)
  • Integer division: div(sum(arr), length(arr))
  • Empty array: Return 0 or handle separately
  • Precision: Returns Float64
julia
# Average of array
function average_array(arr)
    return sum(arr) / length(arr)
end
println(average_array([1, 2, 3, 4, 5])) # 3.0

# With integer division
function average_integer(arr)
    return div(sum(arr), length(arr))
end
Coding Round
58. Sort array ascending

Sort an array in ascending order using sort. Use sort! for in-place sorting.

  • Non-mutating: sort(arr)
  • Mutating: sort!(arr)
  • Custom comparator: sort(arr, by = x -> x)
  • Strings: Sort lexicographically
julia
# Sort array ascending
function sort_ascending(arr)
    return sort(arr)
end
println(sort_ascending([5, 2, 8, 1, 9])) # [1, 2, 5, 8, 9]

# In-place sorting
function sort_ascending!(arr)
    sort!(arr)
    return arr
end
Coding Round
59. Sort array descending

Sort an array in descending order using sort with rev=true.

  • Non-mutating: sort(arr, rev=true)
  • Mutating: sort!(arr, rev=true)
  • Alternative: sort(arr) |> reverse
  • Custom comparator: sort(arr, by = x -> -x)
julia
# Sort array descending
function sort_descending(arr)
    return sort(arr, rev=true)
end
println(sort_descending([5, 2, 8, 1, 9])) # [9, 8, 5, 2, 1]

# In-place sorting
function sort_descending!(arr)
    sort!(arr, rev=true)
    return arr
end
Coding Round
60. Flatten nested array

Flatten a nested array using recursion or vec for simple arrays. Handle multiple levels of nesting.

  • Recursive: Iterate and flatten sub-arrays
  • vec: vec(arr) for simple cases
  • Deep flatten: Custom recursive function
  • Complexity: O(n) time
julia
# Flatten nested array
function flatten_array(arr)
    result = []
    for x in arr
        if isa(x, Vector)
            append!(result, flatten_array(x))
        else
            push!(result, x)
        end
    end
    return result
end
println(flatten_array([1, [2, [3, 4], 5], 6])) # [1, 2, 3, 4, 5, 6]

# Using Base function
function flatten_using_base(arr)
    return vec(arr)
end
Coding Round
61. Chunk array

Split an array into chunks of a specified size using slicing in a loop.

  • Method: arr[i:min(i+size-1, end)]
  • Step: i:size:length(arr)
  • Incomplete chunk: Handle remaining elements
  • Use case: Batch processing
julia
# Chunk array
function chunk_array(arr, size::Int)
    chunks = []
    for i in 1:size:length(arr)
        push!(chunks, arr[i:min(i+size-1, end)])
    end
    return chunks
end
println(chunk_array([1, 2, 3, 4, 5, 6], 2)) # [[1, 2], [3, 4], [5, 6]]
Coding Round
63. Quick sort

Implement quick sort using a pivot and recursion. Partition the array around the pivot.

  • Algorithm: Choose pivot, partition, recurse
  • Time: O(n log n) average, O(n²) worst
  • In-place: Implement in-place for performance
  • Pivot choice: First, last, or random
julia
# Quick sort
function quick_sort(arr)
    if length(arr) <= 1
        return arr
    end
    pivot = arr[1]
    left = [x for x in arr[2:end] if x < pivot]
    right = [x for x in arr[2:end] if x >= pivot]
    return [quick_sort(left)..., pivot, quick_sort(right)...]
end
println(quick_sort([5, 3, 8, 4, 2, 7, 1, 6]))

# In-place quick sort
function quick_sort!(arr, first, last)
    if first < last
        splitpoint = partition!(arr, first, last)
        quick_sort!(arr, first, splitpoint-1)
        quick_sort!(arr, splitpoint+1, last)
    end
    return arr
end
Coding Round
64. Merge sort

Implement merge sort using divide-and-conquer. Merge two sorted sub-arrays.

  • Algorithm: Divide, sort, merge
  • Time: O(n log n)
  • Stable: Maintains relative order
  • Space: O(n) auxiliary space
julia
# Merge sort
function merge_sort(arr)
    if length(arr) <= 1
        return arr
    end
    mid = div(length(arr), 2)
    left = merge_sort(arr[1:mid])
    right = merge_sort(arr[mid+1:end])
    return merge(left, right)
end

function merge(left, right)
    result = []
    i, j = 1, 1
    while i <= length(left) && j <= length(right)
        if left[i] <= right[j]
            push!(result, left[i])
            i += 1
        else
            push!(result, right[j])
            j += 1
        end
    end
    append!(result, left[i:end])
    append!(result, right[j:end])
    return result
end

println(merge_sort([5, 3, 8, 4, 2, 7, 1, 6]))
Coding Round
65. Bubble sort

Implement bubble sort with optimization to stop early if no swaps occur.

  • Algorithm: Compare adjacent, swap if needed
  • Time: O(n²) worst case
  • Optimization: Early termination
  • Use case: Educational, small datasets
julia
# Bubble sort
function bubble_sort(arr)
    sorted = copy(arr)
    n = length(sorted)
    for i in 1:n-1
        for j in 1:n-i
            if sorted[j] > sorted[j+1]
                sorted[j], sorted[j+1] = sorted[j+1], sorted[j]
            end
        end
    end
    return sorted
end
println(bubble_sort([5, 3, 8, 4, 2, 7, 1, 6]))

# Optimized bubble sort
function bubble_sort_optimized(arr)
    sorted = copy(arr)
    n = length(sorted)
    for i in 1:n-1
        swapped = false
        for j in 1:n-i
            if sorted[j] > sorted[j+1]
                sorted[j], sorted[j+1] = sorted[j+1], sorted[j]
                swapped = true
            end
        end
        if !swapped
            break
        end
    end
    return sorted
end
Coding Round
66. Intersection of arrays

Find common elements between two arrays using list comprehension or Set operations.

  • Comprehension: [x for x in arr1 if x in arr2]
  • Set: intersect(Set(arr1), Set(arr2))
  • Efficiency: Use Set for O(n) time
  • Duplicates: Set removes duplicates
julia
# Intersection of arrays
function intersection(arr1, arr2)
    return [x for x in arr1 if x in arr2]
end
println(intersection([1, 2, 3, 4], [3, 4, 5, 6])) # [3, 4]

# Using Set for efficiency
function intersection_set(arr1, arr2)
    set2 = Set(arr2)
    return [x for x in arr1 if x in set2]
end
Coding Round
67. Union of arrays

Combine two arrays with unique elements using Set operations.

  • Set: collect(Set([arr1..., arr2...]))
  • Unique: unique(vcat(arr1, arr2))
  • Order: Set doesn't preserve order
  • Efficiency: O(n) time
julia
# Union of arrays
function union(arr1, arr2)
    return collect(Set([arr1..., arr2...]))
end
println(union([1, 2, 3], [3, 4, 5])) # [1, 2, 3, 4, 5]

# Alternative using vcat and unique
function union_alt(arr1, arr2)
    return unique(vcat(arr1, arr2))
end
Coding Round
68. Difference of arrays

Find elements in the first array that are not in the second array.

  • Comprehension: [x for x in arr1 if x not in arr2]
  • Symmetric: [difference(arr1, arr2)..., difference(arr2, arr1)...]
  • Efficiency: Use Set for O(n) time
  • Use case: Set operations
julia
# Difference of arrays
function difference(arr1, arr2)
    return [x for x in arr1 if x not in arr2]
end
println(difference([1, 2, 3, 4], [3, 4, 5, 6])) # [1, 2]

# Symmetric difference
function symmetric_difference(arr1, arr2)
    return [difference(arr1, arr2)..., difference(arr2, arr1)...]
end
Coding Round
69. Group by property

Group an array of objects by a property using a dictionary.

  • Method: Iterate and group into dict
  • Key: Use property as key
  • Value: Array of items with that key
  • Use case: Data aggregation
julia
# Group by property
function group_by(arr, key)
    groups = Dict()
    for item in arr
        group_key = getproperty(item, key)
        if haskey(groups, group_key)
            push!(groups[group_key], item)
        else
            groups[group_key] = [item]
        end
    end
    return groups
end

data = [
    (type="fruit", name="apple"),
    (type="fruit", name="banana"),
    (type="veg", name="carrot")
]
println(group_by(data, :type))
Coding Round
70. Deep clone object

Create a deep copy of an object by recursively copying nested structures.

  • Method: Recursive copying
  • Dicts: Copy keys and values recursively
  • Arrays: Copy elements recursively
  • Performance: O(n) where n is object size
julia
# Deep clone object
function deep_clone(obj)
    if isa(obj, Dict)
        return Dict(key => deep_clone(value) for (key, value) in obj)
    elseif isa(obj, Vector)
        return [deep_clone(x) for x in obj]
    elseif isa(obj, Tuple)
        return Tuple(deep_clone(x) for x in obj)
    else
        return obj
    end
end

original = Dict("a" => 1, "b" => Dict("c" => 2))
cloned = deep_clone(original)
cloned["b"]["c"] = 3
println(original["b"]["c"]) # 2
println(cloned["b"]["c"]) # 3
Coding Round
71. Immutable update

Perform immutable updates on nested data structures by copying at each level.

  • Method: Copy object and update path
  • Path: Use dot notation for nested access
  • Libraries: Use Setfield.jl for convenience
  • Use case: State management
julia
# Immutable update
function update_immutable(obj, path, value)
    parts = split(path, ".")
    if length(parts) == 1
        new_obj = copy(obj)
        new_obj[parts[1]] = value
        return new_obj
    else
        first_part = parts[1]
        rest_path = join(parts[2:end], ".")
        new_obj = copy(obj)
        if haskey(new_obj, first_part)
            new_obj[first_part] = update_immutable(new_obj[first_part], rest_path, value)
        else
            new_obj[first_part] = update_immutable(Dict(), rest_path, value)
        end
        return new_obj
    end
end

state = Dict("user" => Dict("name" => "Alice", "age" => 25))
new_state = update_immutable(state, "user.age", 26)
println(state["user"]["age"]) # 25
println(new_state["user"]["age"]) # 26
Coding Round
72. Pipe function

Implement a pipe function that composes functions from left to right.

  • Method: pipe(fns...)(value)
  • Implementation: Reduce with function application
  • Use case: Function composition
  • Direction: Left to right
julia
# Pipe function
function pipe(fns...)
    return function(value)
        result = value
        for fn in fns
            result = fn(result)
        end
        return result
    end
end

double(x) = x * 2
add_ten(x) = x + 10
square(x) = x^2

process = pipe(double, add_ten, square)
println(process(5)) # (5*2+10)^2 = 400
Coding Round
73. Compose function

Implement a compose function that composes functions from right to left.

  • Method: compose(fns...)(value)
  • Implementation: ReduceRight with function application
  • Use case: Function composition
  • Direction: Right to left
julia
# Compose function
function compose(fns...)
    return function(value)
        result = value
        for fn in reverse(fns)
            result = fn(result)
        end
        return result
    end
end

process2 = compose(square, add_ten, double)
println(process2(5)) # (5*2+10)^2 = 400
Coding Round
74. Memoization

Implement memoization to cache function results based on arguments.

  • Method: Cache in dictionary
  • Key: Serialize arguments
  • Use case: Expensive function calls
  • Trade-off: Memory for speed
julia
# Memoization
function memoize(fn)
    cache = Dict()
    return function(args...)
        key = tuple(args...)
        if haskey(cache, key)
            return cache[key]
        end
        result = fn(args...)
        cache[key] = result
        return result
    end
end

fibonacci_memo = memoize(function(n)
    if n <= 1
        return n
    end
    return fibonacci_memo(n-1) + fibonacci_memo(n-2)
end)

println(fibonacci_memo(10))
Coding Round
75. Once function

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

  • Method: Use a flag and closure
  • Implementation: Track if called
  • Use case: Initialization, setup
  • Thread safety: Not needed in single-threaded
julia
# Once function
function once(fn)
    called = false
    result = nothing
    return function(args...)
        if !called
            called = true
            result = fn(args...)
        end
        return result
    end
end

initialize = once(() -> begin
    println("Initialized")
    return Dict("id" => 1, "name" => "App")
end)

initialize()
initialize()
Coding Round
76. Debounce with leading edge

Implement debounce with leading edge execution, which runs immediately on first call then waits.

  • Method: Track last call time
  • Implementation: Immediate execution, then cooldown
  • Use case: Save actions, API calls
  • Difference: Leading vs trailing edge
julia
# Debounce with leading edge
function debounce_leading(fn, delay::Int)
    last_call = 0
    timeout_id = nothing
    return function(args...)
        now_time = time()
        if now_time - last_call < delay
            if timeout_id !== nothing
                cancel(timeout_id)
            end
            timeout_id = @async begin
                sleep(delay)
                last_call = time()
                fn(args...)
            end
        else
            last_call = now_time
            fn(args...)
        end
    end
end
Coding Round
77. Throttle with leading edge

Implement throttle with leading edge execution, which runs at most once per time period.

  • Method: Track last call time
  • Implementation: Execute if enough time has passed
  • Use case: Scroll events, resize events
  • Difference: Leading vs trailing edge
julia
# Throttle with leading edge
function throttle_leading(fn, delay::Int)
    last_call = 0
    return function(args...)
        now_time = time()
        if now_time - last_call >= delay
            last_call = now_time
            fn(args...)
        end
    end
end
Coding Round
78. Deep equal

Implement deep equality comparison for nested structures.

  • Method: Recursive comparison
  • Base cases: Primitive values
  • Objects: Compare keys and values recursively
  • Arrays: Compare elements recursively
julia
# Deep equal
function deep_equal(obj1, obj2)
    if obj1 === obj2
        return true
    end
    if typeof(obj1) != typeof(obj2)
        return false
    end
    if isa(obj1, Dict)
        if length(obj1) != length(obj2)
            return false
        end
        for (key, value) in obj1
            if !haskey(obj2, key)
                return false
            end
            if !deep_equal(value, obj2[key])
                return false
            end
        end
        return true
    elseif isa(obj1, Vector)
        if length(obj1) != length(obj2)
            return false
        end
        for (i, value) in enumerate(obj1)
            if !deep_equal(value, obj2[i])
                return false
            end
        end
        return true
    else
        return obj1 == obj2
    end
end
Coding Round
79. Observable pattern

Implement the Observable pattern for event notification and subscription.

  • Observable: Maintains subscribers
  • Subscribe: Add callback to subscribers
  • Notify: Call all subscribers
  • Unsubscribe: Remove callback
julia
# Observable pattern
mutable struct Observable
    subscribers::Vector{Function}
end

function Observable()
    return Observable(Function[])
end

function subscribe(obs::Observable, callback::Function)
    push!(obs.subscribers, callback)
    return function()
        filter!(x -> x !== callback, obs.subscribers)
    end
end

function notify(obs::Observable, data)
    for callback in obs.subscribers
        callback(data)
    end
end

# Usage
obs = Observable()
unsubscribe = subscribe(obs, data -> println("Received: $data"))
notify(obs, "Hello") # Received: Hello
unsubscribe()
notify(obs, "World") # Nothing happens
Coding Round
80. Singleton pattern

Implement the Singleton pattern to ensure only one instance of a class exists.

  • Method: Store instance in a constant
  • Lazy: Create instance only when needed
  • Global: Access from anywhere
  • Use case: Configuration, logging
julia
# Singleton pattern
mutable struct Singleton
    data::Dict
end

function Singleton()
    if !isdefined(@__MODULE__, :_singleton_instance)
        @eval const _singleton_instance = Singleton(Dict())
    end
    return _singleton_instance
end

function set_value(s::Singleton, key, value)
    s.data[key] = value
end

function get_value(s::Singleton, key)
    return get(s.data, key, nothing)
end

# Usage
s1 = Singleton()
s2 = Singleton()
set_value(s1, "name", "Alice")
println(get_value(s2, "name")) # Alice
println(s1 === s2) # true
Coding Round
81. Factory pattern

Implement the Factory pattern for creating objects without specifying the exact class.

  • Method: Factory function or class
  • Benefits: Decouples creation from usage
  • Parameterized: Pass parameters for customization
  • Use case: Creating different types
julia
# Factory pattern
abstract type User end

struct Admin <: User
    name::String
end

struct Guest <: User
    name::String
end

struct RegularUser <: User
    name::String
end

function create_user(type::String, name::String)
    if type == "admin"
        return Admin(name)
    elseif type == "guest"
        return Guest(name)
    else
        return RegularUser(name)
    end
end

# Usage
admin = create_user("admin", "Alice")
println(typeof(admin)) # Admin
Coding Round
82. Strategy pattern

Implement the Strategy pattern for interchangeable algorithms.

  • Context: Uses a strategy
  • Strategy: Interface for algorithms
  • Benefits: Runtime switching
  • Use case: Payment methods, sorting
julia
# Strategy pattern
abstract type PaymentStrategy end

struct CreditCardStrategy <: PaymentStrategy end
struct PayPalStrategy <: PaymentStrategy end
struct CryptoStrategy <: PaymentStrategy end

function pay(strategy::CreditCardStrategy, amount::Float64)
    println("Paid $amount with Credit Card")
end

function pay(strategy::PayPalStrategy, amount::Float64)
    println("Paid $amount with PayPal")
end

function pay(strategy::CryptoStrategy, amount::Float64)
    println("Paid $amount with Crypto")
end

mutable struct PaymentContext
    strategy::PaymentStrategy
end

function execute_payment(context::PaymentContext, amount::Float64)
    pay(context.strategy, amount)
end

# Usage
context = PaymentContext(CreditCardStrategy())
execute_payment(context, 100.0)
context.strategy = PayPalStrategy()
execute_payment(context, 50.0)
Coding Round
83. Observer pattern

Implement the Observer pattern for one-to-many dependency notification.

  • Subject: Maintains observers
  • Observer: Receives updates
  • Benefits: Loose coupling
  • Use case: Event handling, pub/sub
julia
# Observer pattern
mutable struct Subject
    observers::Vector{Function}
    state::String
end

function Subject()
    return Subject([], "")
end

function attach(subject::Subject, observer::Function)
    push!(subject.observers, observer)
end

function detach(subject::Subject, observer::Function)
    filter!(x -> x !== observer, subject.observers)
end

function notify(subject::Subject)
    for observer in subject.observers
        observer(subject.state)
    end
end

function set_state(subject::Subject, state::String)
    subject.state = state
    notify(subject)
end

# Usage
subject = Subject()
observer1(data) = println("Observer1 received: $data")
observer2(data) = println("Observer2 received: $data")
attach(subject, observer1)
attach(subject, observer2)
set_state(subject, "Hello World")
Coding Round
84. Decorator pattern

Implement the Decorator pattern for adding behavior dynamically.

  • Component: Base interface
  • Decorator: Wraps component
  • Benefits: Flexible extension
  • Use case: Logging, authentication
julia
# Decorator pattern
struct Coffee
    cost::Float64
    description::String
end

function milk_decorator(coffee::Coffee)
    return Coffee(coffee.cost + 2.0, coffee.description * ", Milk")
end

function sugar_decorator(coffee::Coffee)
    return Coffee(coffee.cost + 1.0, coffee.description * ", Sugar")
end

# Usage
coffee = Coffee(5.0, "Coffee")
coffee = milk_decorator(coffee)
coffee = sugar_decorator(coffee)
println(coffee.description) # Coffee, Milk, Sugar
println(coffee.cost) # 8.0
Coding Round
85. Command pattern

Implement the Command pattern for encapsulating requests.

  • Command: Encapsulates request
  • Invoker: Executes commands
  • Receiver: Performs work
  • Benefits: Undo/redo, queuing
julia
# Command pattern
abstract type Command end

mutable struct AddCommand <: Command
    receiver::Vector{Int}
    value::Int
end

function execute(cmd::AddCommand)
    push!(cmd.receiver, cmd.value)
end

function undo(cmd::AddCommand)
    pop!(cmd.receiver)
end

# Usage
receiver = [1, 2, 3]
cmd = AddCommand(receiver, 4)
execute(cmd)
println(receiver) # [1, 2, 3, 4]
undo(cmd)
println(receiver) # [1, 2, 3]
Coding Round
86. Memento pattern

Implement the Memento pattern for state capture and restoration.

  • Originator: Creates and restores mementos
  • Memento: Stores internal state
  • Caretaker: Manages mementos
  • Benefits: Undo/redo
julia
# Memento pattern
mutable struct Memento
    state::Dict
end

mutable struct Originator
    state::Dict
end

function save_state(originator::Originator)
    return Memento(copy(originator.state))
end

function restore_state(originator::Originator, memento::Memento)
    originator.state = memento.state
end

mutable struct Caretaker
    mementos::Vector{Memento}
end

function Caretaker()
    return Caretaker([])
end

# Usage
originator = Originator(Dict("value" => 1))
caretaker = Caretaker()

push!(caretaker.mementos, save_state(originator))
originator.state["value"] = 2
push!(caretaker.mementos, save_state(originator))
originator.state["value"] = 3

restore_state(originator, caretaker.mementos[1])
println(originator.state["value"]) # 1
Coding Round
87. Mediator pattern

Implement the Mediator pattern for centralized communication.

  • Mediator: Encapsulates communication
  • Colleague: Communicates through mediator
  • Benefits: Loose coupling
  • Use case: Chat systems, UI components
julia
# Mediator pattern
mutable struct Colleague
    name::String
    mediator::Any
end

mutable struct Mediator
    colleagues::Vector{Colleague}
end

function Mediator()
    return Mediator([])
end

function register(mediator::Mediator, colleague::Colleague)
    colleague.mediator = mediator
    push!(mediator.colleagues, colleague)
end

function send(mediator::Mediator, message::String, sender::Colleague)
    for colleague in mediator.colleagues
        if colleague !== sender
            receive(colleague, message)
        end
    end
end

function receive(colleague::Colleague, message::String)
    println("$(colleague.name) received: $message")
end

# Usage
mediator = Mediator()
alice = Colleague("Alice", mediator)
bob = Colleague("Bob", mediator)
register(mediator, alice)
register(mediator, bob)
send(mediator, "Hello Bob!", alice)
Coding Round
88. Chain of Responsibility

Implement the Chain of Responsibility pattern for processing requests.

  • Handler: Processes or forwards request
  • Chain: Linked list of handlers
  • Benefits: Decoupling
  • Use case: Logging, authentication
julia
# Chain of Responsibility
abstract type Handler end

mutable struct AuthHandler <: Handler
    next_handler::Union{Handler, Nothing}
end

function AuthHandler()
    return AuthHandler(nothing)
end

mutable struct LoggerHandler <: Handler
    next_handler::Union{Handler, Nothing}
end

function LoggerHandler()
    return LoggerHandler(nothing)
end

function set_next(handler::Handler, next_handler::Handler)
    handler.next_handler = next_handler
    return next_handler
end

function handle(handler::AuthHandler, request::Dict)
    if haskey(request, "token")
        println("Authentication passed")
        if handler.next_handler !== nothing
            handle(handler.next_handler, request)
        end
    else
        println("Authentication failed")
    end
end

function handle(handler::LoggerHandler, request::Dict)
    println("Logging request: $(get(request, "url", "unknown"))")
    if handler.next_handler !== nothing
        handle(handler.next_handler, request)
    end
end

# Usage
auth = AuthHandler()
logger = LoggerHandler()
set_next(auth, logger)
handle(auth, Dict("token" => "valid", "url" => "/api"))
Coding Round
89. State pattern

Implement the State pattern for changing behavior with state.

  • Context: Maintains state
  • State: Defines behavior
  • Benefits: Clean state management
  • Use case: State machines
julia
# State pattern
abstract type State end

struct ReadyState <: State end
struct ProcessingState <: State end
struct CompletedState <: State end

mutable struct Context
    state::State
end

function Context()
    return Context(ReadyState())
end

function set_state(context::Context, state::State)
    context.state = state
end

function handle(context::Context, state::ReadyState)
    println("Ready: Waiting for input")
end

function handle(context::Context, state::ProcessingState)
    println("Processing: Working on task")
end

function handle(context::Context, state::CompletedState)
    println("Completed: Task finished")
end

function request(context::Context)
    handle(context, context.state)
end

# Usage
context = Context()
request(context) # Ready: Waiting for input
set_state(context, ProcessingState())
request(context) # Processing: Working on task
set_state(context, CompletedState())
request(context) # Completed: Task finished
Coding Round
90. Proxy pattern

Implement the Proxy pattern for controlling access to objects.

  • Subject: Real object
  • Proxy: Controls access
  • Benefits: Access control, lazy loading
  • Use case: Virtual proxies, protection
julia
# Proxy pattern
struct RealSubject end

function request(::RealSubject)
    println("RealSubject: Handling request")
end

mutable struct Proxy
    real_subject::Union{RealSubject, Nothing}
end

function Proxy()
    return Proxy(nothing)
end

function request(proxy::Proxy)
    if proxy.real_subject === nothing
        proxy.real_subject = RealSubject()
    end
    if check_access()
        request(proxy.real_subject)
        log_access()
    end
end

function check_access()
    println("Proxy: Checking access")
    return true
end

function log_access()
    println("Proxy: Logging access")
end

# Usage
proxy = Proxy()
request(proxy)
Coding Round
91. Flyweight pattern

Implement the Flyweight pattern for sharing objects to save memory.

  • Flyweight: Shared object
  • Factory: Manages flyweights
  • Benefits: Memory optimization
  • Use case: Text rendering, caching
julia
# Flyweight pattern
mutable struct Flyweight
    shared_state::String
end

function operation(flyweight::Flyweight, unique_state::String)
    println("Shared: $(flyweight.shared_state), Unique: $unique_state")
end

mutable struct FlyweightFactory
    flyweights::Dict{String, Flyweight}
end

function FlyweightFactory()
    return FlyweightFactory(Dict{String, Flyweight}())
end

function get_flyweight(factory::FlyweightFactory, shared_state::String)
    if !haskey(factory.flyweights, shared_state)
        factory.flyweights[shared_state] = Flyweight(shared_state)
    end
    return factory.flyweights[shared_state]
end

# Usage
factory = FlyweightFactory()
fw1 = get_flyweight(factory, "state1")
fw2 = get_flyweight(factory, "state1")
fw3 = get_flyweight(factory, "state2")
operation(fw1, "unique1")
operation(fw2, "unique2")
operation(fw3, "unique3")
Coding Round
92. Bridge pattern

Implement the Bridge pattern for separating abstraction from implementation.

  • Abstraction: High-level interface
  • Implementation: Low-level operations
  • Benefits: Separation of concerns
  • Use case: Cross-platform
julia
# Bridge pattern
abstract type Implementation end

struct ConcreteImplementationA <: Implementation end
struct ConcreteImplementationB <: Implementation end

function operation(impl::Implementation)
    if isa(impl, ConcreteImplementationA)
        println("ConcreteImplementationA: Operation")
    elseif isa(impl, ConcreteImplementationB)
        println("ConcreteImplementationB: Operation")
    end
end

mutable struct Abstraction
    impl::Implementation
end

function operation(abstraction::Abstraction)
    println("Abstraction: Additional logic")
    operation(abstraction.impl)
end

# Usage
impl_a = ConcreteImplementationA()
impl_b = ConcreteImplementationB()
abstraction1 = Abstraction(impl_a)
abstraction2 = Abstraction(impl_b)
operation(abstraction1)
operation(abstraction2)
Coding Round
93. Adapter pattern

Implement the Adapter pattern for converting interfaces.

  • Target: Expected interface
  • Adaptee: Existing interface
  • Adapter: Bridges target and adaptee
  • Benefits: Reusability, legacy integration
julia
# Adapter pattern
struct Target end
function request(::Target)
    println("Target: Request")
end

struct Adaptee end
function specific_request(::Adaptee)
    println("Adaptee: Specific Request")
end

mutable struct Adapter
    adaptee::Adaptee
end

function request(adapter::Adapter)
    specific_request(adapter.adaptee)
end

# Usage
adaptee = Adaptee()
adapter = Adapter(adaptee)
request(adapter)
Coding Round
94. Facade pattern

Implement the Facade pattern for simplifying complex subsystems.

  • Facade: Simplified interface
  • Subsystem: Complex components
  • Benefits: Simplified interface
  • Use case: Library APIs
julia
# Facade pattern
struct SubsystemA end
struct SubsystemB end

function operation_a(::SubsystemA)
    println("SubsystemA: Operation")
end

function operation_b(::SubsystemB)
    println("SubsystemB: Operation")
end

mutable struct Facade
    subsystem_a::SubsystemA
    subsystem_b::SubsystemB
end

function Facade()
    return Facade(SubsystemA(), SubsystemB())
end

function operation(facade::Facade)
    operation_a(facade.subsystem_a)
    operation_b(facade.subsystem_b)
    println("Facade: Complex operation")
end

# Usage
facade = Facade()
operation(facade)
Coding Round
95. Composite pattern

Implement the Composite pattern for tree structures.

  • Component: Interface for all objects
  • Leaf: Individual object
  • Composite: Container of components
  • Benefits: Uniform interface
julia
# Composite pattern
abstract type Component end

struct Leaf <: Component
    name::String
end

function operation(leaf::Leaf)
    println("Leaf $(leaf.name): Operation")
end

mutable struct Composite <: Component
    name::String
    children::Vector{Component}
end

function Composite(name::String)
    return Composite(name, [])
end

function add(composite::Composite, component::Component)
    push!(composite.children, component)
end

function remove(composite::Composite, component::Component)
    filter!(x -> x !== component, composite.children)
end

function operation(composite::Composite)
    println("Composite $(composite.name): Operation")
    for child in composite.children
        operation(child)
    end
end

# Usage
leaf1 = Leaf("A")
leaf2 = Leaf("B")
composite = Composite("Root")
add(composite, leaf1)
add(composite, leaf2)
operation(composite)
Coding Round
96. Visitor pattern

Implement the Visitor pattern for adding operations to objects.

  • Visitor: Defines operations
  • Element: Accepts visitors
  • Benefits: Adding operations without modifying
  • Use case: Compilers, AST
julia
# Visitor pattern
abstract type Element end

struct ElementA <: Element end
struct ElementB <: Element end

abstract type Visitor end

struct ConcreteVisitor <: Visitor end

function visit(visitor::ConcreteVisitor, element::ElementA)
    println("Visiting ElementA")
end

function visit(visitor::ConcreteVisitor, element::ElementB)
    println("Visiting ElementB")
end

function accept(element::ElementA, visitor::ConcreteVisitor)
    visit(visitor, element)
end

function accept(element::ElementB, visitor::ConcreteVisitor)
    visit(visitor, element)
end

# Usage
visitor = ConcreteVisitor()
element_a = ElementA()
element_b = ElementB()
accept(element_a, visitor)
accept(element_b, visitor)
Coding Round
97. Iterator pattern

Implement the Iterator pattern for sequential access.

  • Iterator: Traverses collection
  • Aggregate: Creates iterator
  • Benefits: Uniform traversal
  • Use case: Collection traversal
julia
# Iterator pattern
mutable struct Iterator
    collection::Vector
    index::Int
end

function Iterator(collection::Vector)
    return Iterator(collection, 1)
end

function next(iterator::Iterator)
    item = iterator.collection[iterator.index]
    iterator.index += 1
    return item
end

function has_next(iterator::Iterator)
    return iterator.index <= length(iterator.collection)
end

mutable struct CustomCollection
    items::Vector
end

function CustomCollection()
    return CustomCollection([])
end

function add(collection::CustomCollection, item)
    push!(collection.items, item)
end

function get_iterator(collection::CustomCollection)
    return Iterator(collection.items)
end

# Usage
collection = CustomCollection()
add(collection, "A")
add(collection, "B")
add(collection, "C")
iterator = get_iterator(collection)
while has_next(iterator)
    println(next(iterator))
end
Coding Round
98. Template Method pattern

Implement the Template Method pattern for algorithm skeletons.

  • AbstractClass: Defines template method
  • ConcreteClass: Implements steps
  • Benefits: Code reuse
  • Use case: Frameworks, algorithms
julia
# Template Method pattern
abstract type AbstractClass end

function template_method(::AbstractClass)
    println("Step 1")
    println("Step 2")
    println("Step 3")
end

mutable struct ConcreteClass <: AbstractClass end

function template_method(concrete::ConcreteClass)
    println("Step 1")
    concrete_step2()
    println("Step 3")
end

function concrete_step2()
    println("Concrete Step 2")
end

# Usage
concrete = ConcreteClass()
template_method(concrete)
Coding Round
99. Builder pattern

Implement the Builder pattern for constructing complex objects.

  • Builder: Constructs parts
  • Director: Orchestrates construction
  • Product: Constructed object
  • Benefits: Step-by-step construction
julia
# Builder pattern
mutable struct Product
    parts::Vector{String}
end

function Product()
    return Product([])
end

function add(product::Product, part::String)
    push!(product.parts, part)
end

function list_parts(product::Product)
    println(join(product.parts, ", "))
end

mutable struct Builder
    product::Product
end

function Builder()
    return Builder(Product())
end

function reset(builder::Builder)
    builder.product = Product()
end

function build_step_a(builder::Builder)
    add(builder.product, "Part A")
end

function build_step_b(builder::Builder)
    add(builder.product, "Part B")
end

function get_result(builder::Builder)
    return builder.product
end

mutable struct Director
    builder::Builder
end

function build_minimal(director::Director)
    build_step_a(director.builder)
end

function build_full(director::Director)
    build_step_a(director.builder)
    build_step_b(director.builder)
end

# Usage
builder = Builder()
director = Director(builder)
build_minimal(director)
product = get_result(builder)
list_parts(product)
Coding Round
100. Prototype pattern

Implement the Prototype pattern for cloning objects.

  • Prototype: Cloneable object
  • Clone: Creates a copy
  • Benefits: Performance, avoids constructors
  • Use case: Complex objects
julia
# Prototype pattern
mutable struct Prototype
    name::String
    nested::Dict
end

function clone(prototype::Prototype)
    return Prototype(prototype.name, copy(prototype.nested))
end

function deep_clone(prototype::Prototype)
    return Prototype(prototype.name, deepcopy(prototype.nested))
end

# Usage
original = Prototype("Original", Dict("value" => 42))
copy = clone(original)
copy.name = "Copy"
copy.nested["value"] = 99
println(original.name) # Original
println(original.nested["value"]) # 42 (shallow copy)

deep_copy = deep_clone(original)
deep_copy.nested["value"] = 100
println(original.nested["value"]) # 42 (deep copy)