InterviewPitch
DART interview questions

DART Interview Questions with Answers

Most Asked DART Interview Questions for Software Engineer Roles

100+ QuestionsDetailed AnswersCode ExamplesUpdated for 2026

Introduction

Dart is a client‑optimized language for fast apps on any platform. This page compiles the most frequently asked Dart interview questions, covering everything from basic syntax to advanced OOP, functional programming, and concurrency – essential for Flutter and full‑stack development.

Why Dart?

  • Object‑oriented with sound null safety
  • JIT & AOT compilation for fast development and performance
  • Modern language features – async/await, generics, mixins
  • Powerful standard library with collections and streams
  • Used by Flutter – the world’s most popular cross‑platform framework
  • Growing community and enterprise adoption

Most Asked DART Interview Questions

Beginner
1. What is Dart and what are its key features?

Dart is a client-optimized programming language developed by Google. It's used for building web, mobile (Flutter), and desktop applications with a focus on productivity and performance.

  • Object-Oriented: Everything is an object
  • Type Safety: Strong static typing with type inference
  • Sound Null Safety: Prevents null reference errors
  • Async/Await: Built-in support for asynchronous programming
  • JIT & AOT Compilation: Fast development and production performance
dart
// Hello World in Dart
void main() {
  print('Hello, World!');
}
Beginner
2. What are Data Types in Dart?

Dart provides a rich set of built-in data types including numbers, strings, booleans, lists, sets, and maps. All types are objects and inherit from Object.

  • int — 64-bit integer (depending on platform)
  • double — 64-bit floating point
  • String — UTF-16 encoded text
  • bool — true/false
  • List — ordered collection
  • Set — unordered unique collection
  • Map — key-value pairs
dart
// Data Types in Dart
void main() {
  int age = 25;
  double salary = 50000.50;
  double pi = 3.14159265358979;
  String grade = 'A';
  bool isActive = true;
  String name = "Alice";
  num price = 99.99;

  print('Age: $age');
  print('Salary: $salary');
  print('Pi: $pi');
  print('Grade: $grade');
  print('Active: $isActive');
  print('Name: $name');
  print('Price: $price');
}
Beginner
3. What are Variables, Constants, and Final in Dart?

Dart uses var for type inference, final for runtime constants, and const for compile-time constants. It also supports explicit type declarations.

  • var — type-inferred variable
  • final — set once at runtime
  • const — compile-time constant
  • late — lazy initialization
  • Explicit typing — int x = 10;
dart
// Variables, Constants, and Final
class Program {
  static const double PI = 3.14159;
  static final int MAX = 100;

  static void main() {
    int x = 10;
    const int MIN_VALUE = 0;
    
    // Type inference
    var val = 3.14;
    var str = "Hello";
    
    print('x = $x');
    print('PI = $PI');
    print('val = $val');
    print('str = $str');
  }
}

void main() => Program.main();
Beginner
4. How do Classes and Objects work in Dart?

A class in Dart encapsulates data and behavior. Dart uses constructors, getters, setters, and methods to define class behavior.

  • class — defines a class
  • new — creates an instance (optional)
  • this — refers to current instance
  • Getters/Setters — property access control
  • @override — method overriding
dart
// OOP - Classes and Objects
class Car {
  String brand;
  int year;
  double price;

  // Constructor
  Car(this.brand, this.year, this.price);

  // Getter methods
  String get Brand => brand;
  int get Year => year;
  double get Price => price;

  // Method
  void display() {
    print('Brand: $brand, Year: $year, Price: $$price');
  }

  // Destructor (not needed in Dart - garbage collected)
}

void main() {
  Car c1 = Car('Toyota', 2022, 25000.0);
  Car c2 = Car('BMW', 2023, 55000.0);

  c1.display();
  c2.display();
  print('Brand: ${c1.Brand}');
}
Beginner
5. What are Constructors in Dart?

Constructors initialize class instances. Dart supports default, parameterized, named, and factory constructors.

  • ClassName() — default constructor
  • ClassName(this.param) — parameterized
  • ClassName.name() — named constructor
  • factory — factory constructor
  • const — compile-time constructor
dart
// Constructors in Dart
class Student {
  String name;
  int age;

  // Default constructor
  Student() : this.name = 'Unknown', this.age = 0 {
    print('Default constructor called');
  }

  // Parameterized constructor
  Student(this.name, this.age) {
    print('Parameterized constructor: $name');
  }

  // Named constructor (copy constructor)
  Student.copy(Student other)
      : name = other.name,
        age = other.age {
    print('Copy constructor: $name');
  }

  void display() {
    print('Name: $name, Age: $age');
  }
}

void main() {
  Student s1 = Student();
  Student s2 = Student('Alice', 20);
  Student s3 = Student.copy(s2);

  s1.display();
  s2.display();
  s3.display();
}
Intermediate
6. How does Inheritance work in Dart?

Inheritance allows classes to reuse and extend behavior. Dart uses single inheritance but supports multiple interfaces and mixins.

  • extends — single inheritance
  • super — call parent constructor/method
  • @override — method overriding
  • implements — interface implementation
  • with — mixin application
dart
// Inheritance in Dart
class Animal {
  String name;
  int age;

  Animal(this.name, this.age);

  void speak() {
    print('$name makes a sound.');
  }

  void info() {
    print('Name: $name, Age: $age');
  }
}

class Dog extends Animal {
  String breed;

  Dog(String name, int age, this.breed) : super(name, age);

  @override
  void speak() {
    print('$name says: Woof!');
  }

  void display() {
    info();
    print('Breed: $breed');
  }
}

class Cat extends Animal {
  Cat(String name, int age) : super(name, age);

  @override
  void speak() {
    print('$name says: Meow!');
  }
}

void main() {
  Dog dog = Dog('Rex', 3, 'German Shepherd');
  Cat cat = Cat('Whiskers', 2);

  dog.display();
  dog.speak();
  cat.speak();

  // Polymorphism via base reference
  Animal a = dog;
  a.speak();
}
Intermediate
7. What is Polymorphism and how do Abstract Classes work in Dart?

Polymorphism allows objects of different types to be treated uniformly. Abstract classes define contracts that derived classes must implement.

  • abstract class — cannot be instantiated
  • @override — implement abstract methods
  • Runtime Polymorphism: Dynamic method dispatch
  • Interface Segregation: Define clear contracts
dart
// Polymorphism and Abstract Classes
abstract class Shape {
  double area();
  double perimeter();

  void display() {
    print('Area: ${area()}, Perimeter: ${perimeter()}');
  }
}

class Circle extends Shape {
  double radius;

  Circle(this.radius);

  @override
  double area() => 3.14159 * radius * radius;

  @override
  double perimeter() => 2 * 3.14159 * radius;
}

class Rectangle extends Shape {
  double width, height;

  Rectangle(this.width, this.height);

  @override
  double area() => width * height;

  @override
  double perimeter() => 2 * (width + height);
}

void main() {
  List<Shape> shapes = [
    Circle(5.0),
    Rectangle(4.0, 6.0)
  ];

  for (var s in shapes) {
    s.display();
  }
}
Intermediate
8. What is Operator Overloading in Dart?

Operator Overloading allows defining custom behavior for operators on user-defined types, making code more intuitive and readable.

  • operator + — addition operator
  • operator - — subtraction operator
  • operator * — multiplication operator
  • operator == — equality comparison
  • hashCode — must be overridden with ==
dart
// Operator Overloading
class Vector2D {
  double x, y;

  Vector2D([this.x = 0, this.y = 0]);

  // + operator
  Vector2D operator +(Vector2D v) {
    return Vector2D(x + v.x, y + v.y);
  }

  // - operator
  Vector2D operator -(Vector2D v) {
    return Vector2D(x - v.x, y - v.y);
  }

  // * scalar
  Vector2D operator *(double s) {
    return Vector2D(x * s, y * s);
  }

  // == operator
  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;
    if (other is! Vector2D) return false;
    return x == other.x && y == other.y;
  }

  @override
  int get hashCode => Object.hash(x, y);

  @override
  String toString() => '($x, $y)';
}

void main() {
  Vector2D v1 = Vector2D(3, 4);
  Vector2D v2 = Vector2D(1, 2);
  
  print('v1 = $v1');
  print('v2 = $v2');
  print('v1 + v2 = ${v1 + v2}');
  print('v1 - v2 = ${v1 - v2}');
  print('v1 * 2 = ${v1 * 2}');
  print('v1 == v2: ${v1 == v2}');
}
Intermediate
9. How do Generics work in Dart?

Generics provide type safety and code reuse by parameterizing types. They enable writing flexible, reusable code while maintaining compile-time type checking.

  • class Stack<T> — generic class
  • T — type parameter
  • extends — type constraints
  • List<int> — generic collection
  • Type Safety: Compile-time checking
dart
// Generics in Dart
// Generic class
class Stack<T> {
  List<T> _data = List.filled(100, null as T);
  int _top = -1;

  void push(T val) {
    _data[++_top] = val;
  }

  T pop() {
    return _data[_top--];
  }

  T peek() {
    return _data[_top];
  }

  bool isEmpty() {
    return _top == -1;
  }
}

// Generic method
T max<T extends Comparable<T>>(T a, T b) {
  return a.compareTo(b) > 0 ? a : b;
}

void swap<T>(T a, T b) {
  // Dart doesn't support ref parameters directly
  // This is a demonstration
  print('Swapping ${a} and ${b}');
}

// Multiple type parameters
class Pair<K, V> {
  K key;
  V value;

  Pair(this.key, this.value);

  void printPair() {
    print('$key -> $value');
  }
}

void main() {
  print(max<int>(10, 20));
  print(max<double>(3.5, 2.1));
  print(max<String>('B', 'A'));

  Stack<int> si = Stack<int>();
  si.push(1);
  si.push(2);
  si.push(3);
  print('${si.pop()} ${si.pop()}');

  Pair<String, int> p = Pair('age', 25);
  p.printPair();
}
Intermediate
10. What are Collections (Lists) in Dart?

Lists are ordered collections of elements. Dart provides extensive list operations including sorting, filtering, mapping, and functional transformations.

  • List<T> — generic list
  • [] — list literal
  • add(), insert() — element operations
  • where(), map() — functional operations
  • sort() — sorting elements
dart
// Collections - Lists
void main() {
  List<int> list = [5, 2, 8, 1, 9, 3];

  // Add elements
  list.add(7);
  list.insert(0, 0);

  // Size
  print('Length: ${list.length}');
  print('Capacity: ${list.length}');

  // Iterate
  print(list.join(' '));

  // Sort
  list.sort();
  print(list.join(' '));

  // Find and remove
  list.remove(8);

  // 2D List
  List<List<int>> mat = List.generate(3, (_) => List.filled(3, 0));
  mat[1][1] = 5;
  print('mat[1][1] = ${mat[1][1]}');

  // Functional methods
  var evens = list.where((x) => x.isEven).toList();
  print('Evens: ${evens.join(', ')}');
}
Intermediate
11. How do Map and Set collections work in Dart?

Maps are key-value pairs while Sets store unique elements. Both provide efficient lookup and data organization.

  • Map<K,V> — key-value dictionary
  • Set<T> — unique elements
  • forEach() — iteration
  • containsKey() — key existence
  • SplayTreeMap — sorted map
dart
// Map and Set
void main() {
  // Map (Dictionary)
  Map<String, int> scores = {};
  scores['Alice'] = 95;
  scores['Bob'] = 87;
  scores['Carol'] = 92;

  scores.forEach((key, value) {
    print('$key: $value');
  });

  print('Alice: ${scores['Alice']}');
  print('Contains Bob: ${scores.containsKey('Bob')}');

  // Set
  Set<int> set = {5, 2, 8, 2, 1, 9, 5};
  print(set.join(' '));

  set.add(6);
  set.remove(2);
  print('Contains 5: ${set.contains(5)}');

  // SplayTreeMap (sorted)
  import 'dart:collection';
  SplayTreeMap<String, int> sorted = SplayTreeMap<String, int>();
  sorted['banana'] = 3;
  sorted['apple'] = 5;
  sorted['cherry'] = 2;
  sorted.forEach((key, value) {
    print('$key: $value');
  });
}
Intermediate
12. What are Stack, Queue, and PriorityQueue in Dart?

Stack (LIFO), Queue (FIFO), and PriorityQueue are specialized collections for specific use cases.

  • Stack: LIFO using List
  • Queue: FIFO using Queue class
  • PriorityQueue: Ordered by priority
  • removeFirst(), removeLast() — operations
  • add(), addAll() — insertion
dart
// Stack, Queue, and PriorityQueue
import 'dart:collection';

void main() {
  // Stack (LIFO) using List
  List<int> stack = [];
  stack.add(10);
  stack.add(20);
  stack.add(30);
  print('Stack top: ${stack.last}');
  while (stack.isNotEmpty) {
    print('${stack.removeLast()} ');
  }
  print('');

  // Queue (FIFO)
  Queue<int> queue = Queue<int>();
  queue.add(10);
  queue.add(20);
  queue.add(30);
  print('Queue front: ${queue.first}');
  while (queue.isNotEmpty) {
    print('${queue.removeFirst()} ');
  }
  print('');

  // PriorityQueue
  import 'package:collection/collection.dart';
  PriorityQueue<String> pq = PriorityQueue<String>((a, b) => a.compareTo(b));
  pq.add('Low');
  pq.add('High');
  pq.add('Medium');
  while (pq.isNotEmpty) {
    print('${pq.removeFirst()} ');
  }
  print('');

  // LinkedList (Doubly-linked)
  LinkedList<DoubleLinkedEntry> ll = LinkedList<DoubleLinkedEntry>();
  // Implementation details omitted for brevity
}
Intermediate
13. How does Exception Handling work in Dart?

Exception Handling provides robust error management with try-catch-finally blocks and custom exception types.

  • try-catch — exception handling
  • throw — raise exceptions
  • finally — cleanup code
  • on — specific exception types
  • Custom Exceptions: Extend Exception class
dart
// Exception Handling
class ValidationError implements Exception {
  final int code;
  final String message;

  ValidationError(this.message, this.code);

  @override
  String toString() => 'ValidationError: $message (code: $code)';
}

double divide(double a, double b) {
  if (b == 0) {
    throw ArgumentError('Division by zero!');
  }
  return a / b;
}

int getAge(int age) {
  if (age < 0 || age > 150) {
    throw ValidationError('Invalid age: $age', 400);
  }
  return age;
}

void main() {
  // Basic try-catch
  try {
    print(divide(10, 2));
    print(divide(10, 0));
  } on ArgumentError catch (e) {
    print('Error: ${e.message}');
  }

  // Custom exception
  try {
    getAge(200);
  } on ValidationError catch (e) {
    print('Validation [${e.code}]: ${e.message}');
  } catch (e) {
    print('General: ${e}');
  }

  // Finally block
  try {
    print('Processing...');
  } finally {
    print('Cleanup always runs');
  }
}
Intermediate
14. How do Disposable and Resource Management work in Dart?

Resource Management ensures proper cleanup of resources like files, network connections, and database handles using try-finally patterns.

  • try-finally — guaranteed cleanup
  • Disposable Pattern: Explicit resource release
  • Garbage Collection: Automatic memory management
  • dispose() — custom cleanup method
dart
// Disposable and Using Statement
class Resource {
  String name;

  Resource(this.name) {
    print('Resource acquired: $name');
  }

  void use() {
    print('Using: $name');
  }

  void dispose() {
    print('Resource released: $name');
  }
}

void main() {
  // Try-finally equivalent
  Resource r1 = Resource('FileResource');
  try {
    r1.use();
  } finally {
    r1.dispose();
  }

  // Using declaration (simulated)
  Resource r2 = Resource('DatabaseResource');
  try {
    r2.use();
  } finally {
    r2.dispose();
  }

  // Try-finally equivalent
  Resource r3 = Resource('NetworkResource');
  try {
    r3.use();
  } finally {
    r3.dispose();
  }
}
Intermediate
15. What are Lambdas and Functional Programming in Dart?

Lambdas and Functional Programming enable concise, declarative code with functions as first-class citizens.

  • () => — arrow function syntax
  • Higher-order Functions: Functions that take functions
  • Closures: Functions with captured variables
  • map(), where(), reduce() — functional operations
dart
// Lambdas and Functional Programming
void main() {
  // Basic lambda
  var greet = (String name) {
    print('Hello, $name!');
  };
  greet('Alice');

  // Function delegate
  int add(int x, int y) => x + y;
  print('Add: ${add(10, 20)}');

  // Lambda with closures
  int x = 10;
  var addX = () => x + 5;
  print('addX: ${addX()}');

  // Functional with lists
  List<int> nums = [5, 1, 8, 3, 9, 2, 7];
  
  // Sort
  nums.sort((a, b) => a.compareTo(b));
  print(nums.join(' '));

  // Filter
  var evens = nums.where((n) => n.isEven).toList();
  print('Evens: ${evens.join(' ')}');

  // Transform
  var squares = nums.map((n) => n * n).toList();
  print('Squares: ${squares.join(' ')}');

  // Reduce
  int sum = nums.reduce((acc, n) => acc + n);
  print('Sum: $sum');
}
Intermediate
16. How do Async/Await and Futures work in Dart?

Async/Await and Futures provide asynchronous programming capabilities for non-blocking operations.

  • Future<T> — asynchronous result
  • async — asynchronous function
  • await — wait for Future
  • Future.wait() — parallel operations
  • Error Handling: try-catch with async
dart
// Async/Await and Futures
import 'dart:async';

Future<String> fetchData(String url, int delay) async {
  await Future.delayed(Duration(milliseconds: delay));
  return 'Data from $url';
}

Future<int> computeAsync(int a, int b) async {
  await Future.delayed(Duration(milliseconds: 100));
  return a + b;
}

void main() async {
  // Basic async
  String result = await fetchData('api.example.com', 500);
  print(result);

  // Parallel async tasks
  List<Future<String>> tasks = [
    fetchData('source1', 300),
    fetchData('source2', 200),
    fetchData('source3', 400)
  ];
  List<String> results = await Future.wait(tasks);
  print('All results: ${results.join(', ')}');

  // Task with exception handling
  try {
    await Future.delayed(Duration(milliseconds: 100), () {
      throw Exception('Task failed');
    });
  } catch (e) {
    print('Caught: ${e}');
  }

  // Parallel processing
  List<int> numbers = List.generate(10, (i) => i + 1);
  List<Future<int>> parallelResults = numbers.map((n) async {
    await Future.delayed(Duration(milliseconds: 50));
    return n * n;
  }).toList();
  List<int> squares = await Future.wait(parallelResults);
  print('Squares: ${squares.join(', ')}');
}
Intermediate
17. How does File I/O work in Dart?

File I/O operations enable reading from and writing to files, directories, and streams in Dart applications.

  • File — file operations
  • readAsString() — reading files
  • writeAsString() — writing files
  • Directory — directory operations
  • FileStat — file metadata
dart
// File I/O in Dart
import 'dart:io';

void main() async {
  // Write to file
  String path = 'students.txt';
  List<String> lines = [
    'Alice 20 3.85',
    'Bob 22 3.62',
    'Carol 21 3.91'
  ];
  await File(path).writeAsString(lines.join('\n'));

  // Read from file
  String content = await File(path).readAsString();
  print(content);

  // Read/Write with Stream
  File output = File('output.txt');
  IOSink sink = output.openWrite();
  sink.writeln('Hello, World!');
  sink.writeln('Line 2');
  await sink.close();

  Stream<String> linesStream = output.openRead()
      .transform(utf8.decoder)
      .transform(LineSplitter());
  await for (String line in linesStream) {
    print(line);
  }

  // File operations
  File('temp.txt').exists().then((exists) {
    if (exists) File('temp.txt').delete();
  });

  // Directory operations
  Directory('testdir').create();
  Directory('testdir').delete();

  // FileInfo
  FileStat stat = await File('students.txt').stat();
  print('File size: ${stat.size} bytes');
  print('Created: ${stat.modified}');

  // CSV parsing
  String csv = 'Alice,Bob,Carol,Dave';
  csv.split(',').forEach((token) => print('$token '));
  print('');
}
Intermediate
18. What are Functional Programming operations with Iterable?

Iterable provides LINQ-like query operations for data transformation and aggregation.

  • map() — transform elements
  • where() — filter elements
  • reduce() — aggregate values
  • fold() — aggregate with initial value
  • groupBy — grouping operations
dart
// Functional Programming with Iterable
void main() {
  List<int> nums = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3];

  // LINQ-like queries
  var unique = nums.toSet().toList()..sort();
  print('Unique: ${unique.join(' ')}');

  // Aggregation
  print('Sum: ${nums.reduce((a, b) => a + b)}');
  print('Min: ${nums.reduce((a, b) => a < b ? a : b)}');
  print('Max: ${nums.reduce((a, b) => a > b ? a : b)}');
  print('Avg: ${nums.reduce((a, b) => a + b) / nums.length}');

  // Conditional counts
  int evens = nums.where((x) => x.isEven).length;
  print('Evens: $evens');

  var firstGreater = nums.firstWhere((x) => x > 4, orElse: () => null);
  print('First > 4: $firstGreater');

  // Transform
  var doubled = nums.map((x) => x * 2).toList();
  print('Doubled: ${doubled.join(' ')}');

  // Group by
  var grouped = nums.fold<Map<String, List<int>>>({}, (map, x) {
    String key = x.isEven ? 'Even' : 'Odd';
    map.putIfAbsent(key, () => []).add(x);
    return map;
  });
  grouped.forEach((key, value) {
    print('$key: ${value.join(', ')}');
  });

  // Zip
  List<int> a = [1, 2, 3];
  List<int> b = [4, 5, 6];
  var zipped = Iterable.generate(a.length, (i) => a[i] + b[i]).toList();
  print('Zipped sum: ${zipped.join(', ')}');
}
Intermediate
19. How do you implement a LinkedList in Dart?

LinkedList is a fundamental data structure for dynamic data storage with efficient insertion and deletion.

  • Node Structure: Data and next pointer
  • Head Tracking: Entry point to list
  • pushFront() — insert at beginning
  • pushBack() — insert at end
  • Traversal: Iterate through nodes
dart
// LinkedList Implementation
class Node<T> {
  T data;
  Node<T>? next;

  Node(this.data) : next = null;
}

class LinkedList<T> {
  Node<T>? head;

  void pushFront(T val) {
    Node<T> node = Node<T>(val);
    node.next = head;
    head = node;
  }

  void pushBack(T val) {
    Node<T> node = Node<T>(val);
    if (head == null) {
      head = node;
      return;
    }
    Node<T> curr = head!;
    while (curr.next != null) {
      curr = curr.next!;
    }
    curr.next = node;
  }

  void display() {
    Node<T>? curr = head;
    while (curr != null) {
      print('${curr.data} -> ');
      curr = curr.next;
    }
    print('null');
  }
}

void main() {
  LinkedList<int> list = LinkedList<int>();
  list.pushBack(10);
  list.pushBack(20);
  list.pushBack(30);
  list.pushFront(5);
  list.display();
}
Intermediate
20. How do Binary Search and Sorting work in Dart?

Binary Search efficiently finds elements in sorted arrays. Sorting arranges elements in a specific order.

  • Binary Search: O(log n) search
  • sort() — built-in sorting
  • indexOf() — linear search
  • Complexity Analysis: Time and space
dart
// Binary Search and Sorting
int binarySearch(List<int> arr, int target) {
  int left = 0;
  int right = arr.length - 1;
  while (left <= right) {
    int mid = left + (right - left) ~/ 2;
    if (arr[mid] == target) return mid;
    if (arr[mid] < target) {
      left = mid + 1;
    } else {
      right = mid - 1;
    }
  }
  return -1;
}

void main() {
  List<int> arr = [2, 5, 8, 12, 16, 23, 38, 56, 72, 91];

  // Manual
  print('Index of 23: ${binarySearch(arr, 23)}');

  // Built-in binary search
  int index = arr.indexOf(56);
  print('Index of 56: $index');

  // Contains
  print('Contains 56: ${arr.contains(56)}');

  // Find methods
  int found = arr.firstWhere((x) => x > 20, orElse: () => -1);
  print('First > 20: $found');

  // Find all
  var greater = arr.where((x) => x > 30).toList();
  print(' > 30: ${greater.join(', ')}');

  // Sort
  arr.sort();
  print('Sorted: ${arr.join(' ')}');
}
Intermediate
21. What is Recursion in Dart?

Recursion is a technique where a function calls itself to solve smaller instances of the same problem.

  • Base Case: Stopping condition
  • Recursive Case: Self-call with smaller input
  • Stack Overflow: Risk of deep recursion
  • Tail Recursion: Optimization technique
dart
// Recursion in Dart
int factorial(int n) {
  if (n <= 1) return 1;
  return n * factorial(n - 1);
}

int fibonacci(int n) {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}

void hanoi(int n, String from, String to, String aux) {
  if (n == 1) {
    print('Move disk 1: $from -> $to');
    return;
  }
  hanoi(n - 1, from, aux, to);
  print('Move disk $n: $from -> $to');
  hanoi(n - 1, aux, to, from);
}

int power(int base, int exp) {
  if (exp == 0) return 1;
  if (exp % 2 == 0) {
    int half = power(base, exp ~/ 2);
    return half * half;
  }
  return base * power(base, exp - 1);
}

void main() {
  print('5! = ${factorial(5)}');
  print('fib(8) = ${fibonacci(8)}');
  print('2^10 = ${power(2, 10)}');
  print('Tower of Hanoi (3 disks):');
  hanoi(3, 'A', 'C', 'B');
}
Intermediate
22. What are Sorting Algorithms in Dart?

Sorting Algorithms like Bubble Sort, Merge Sort, and built-in sort provide different performance characteristics.

  • Bubble Sort: O(n²), simple but slow
  • Merge Sort: O(n log n), efficient
  • Built-in Sort: Optimized implementation
  • Custom Comparators: Flexible sorting
dart
// Sorting Algorithms in Dart
void bubbleSort(List<int> arr) {
  int n = arr.length;
  for (int i = 0; i < n - 1; i++) {
    bool swapped = false;
    for (int j = 0; j < n - i - 1; j++) {
      if (arr[j] > arr[j + 1]) {
        int temp = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = temp;
        swapped = true;
      }
    }
    if (!swapped) break;
  }
}

List<int> mergeSort(List<int> arr) {
  if (arr.length <= 1) return arr;
  int mid = arr.length ~/ 2;
  List<int> left = mergeSort(arr.sublist(0, mid));
  List<int> right = mergeSort(arr.sublist(mid));
  return _merge(left, right);
}

List<int> _merge(List<int> left, List<int> right) {
  List<int> result = [];
  int i = 0, j = 0;
  while (i < left.length && j < right.length) {
    if (left[i] <= right[j]) {
      result.add(left[i++]);
    } else {
      result.add(right[j++]);
    }
  }
  result.addAll(left.sublist(i));
  result.addAll(right.sublist(j));
  return result;
}

void main() {
  List<int> v1 = [64, 34, 25, 12, 22, 11, 90];
  bubbleSort(v1);
  print('Bubble: ${v1.join(' ')}');

  List<int> v2 = [38, 27, 43, 3, 9, 82, 10];
  v2 = mergeSort(v2);
  print('Merge: ${v2.join(' ')}');

  // Built-in sort
  List<int> v3 = [5, 3, 1, 8, 2, 7];
  v3.sort();
  print('Built-in: ${v3.join(' ')}');

  // Sort with comparison
  v3.sort((a, b) => b.compareTo(a));
  print('Descending: ${v3.join(' ')}');
}
Intermediate
23. How does Dynamic Memory and Garbage Collection work in Dart?

Dynamic Memory and Garbage Collection manage memory allocation and deallocation automatically.

  • Heap Memory: Dynamically allocated objects
  • Garbage Collector: Automatic memory reclamation
  • Memory Management: Reference counting vs tracing
  • Memory Leaks: Prevention and detection
dart
// Dynamic Memory and Garbage Collection
class Matrix {
  List<List<int>> data;
  int rows, cols;

  Matrix(this.rows, this.cols) 
      : data = List.generate(rows, (_) => List.filled(cols, 0));

  void set(int r, int c, int val) {
    data[r][c] = val;
  }

  int get(int r, int c) {
    return data[r][c];
  }

  void printMatrix() {
    for (var row in data) {
      print(row.join(' '));
    }
  }
}

void main() {
  // Arrays
  List<int> arr = [10, 20, 30, 40, 50];
  print(arr.join(' '));

  // Multi-dimensional array
  Matrix matrix = Matrix(3, 3);
  matrix.set(0, 0, 1);
  matrix.set(1, 1, 5);
  matrix.set(2, 2, 9);
  matrix.printMatrix();

  // Jagged array
  List<List<int>> jagged = [
    [1, 2],
    [3, 4, 5],
    [6]
  ];

  // Garbage Collection
  print('Total memory: ${process.memoryUsage}');
  // GC is automatic in Dart
}
Intermediate
24. What are String Operations in Dart?

String Operations provide comprehensive text manipulation including concatenation, interpolation, and transformation.

  • Concatenation: + operator or StringBuffer
  • Interpolation: $variable and ${expression}
  • Case Conversion: toLowerCase(), toUpperCase()
  • Split/Join: split(), join()
  • Padding/Trimming: padLeft(), trim()
dart
// String Operations in Dart
void main() {
  String s = 'Hello, World!';

  // Basic operations
  print('Length: ${s.length}');
  print('Substring: ${s.substring(7, 12)}');
  print('Contains: ${s.contains('World')}');
  print('Index of: ${s.indexOf('World')}');

  // StringBuffer (mutable string)
  StringBuffer sb = StringBuffer('Hello');
  sb.write(', World!');
  sb.write(' Dart');
  print(sb.toString());

  // Case conversion
  String lower = s.toLowerCase();
  String upper = s.toUpperCase();
  print('Lower: $lower');
  print('Upper: $upper');

  // Split and join
  String csv = 'Alice,Bob,Carol,Dave';
  List<String> tokens = csv.split(',');
  print(tokens.join(' '));

  // String interpolation
  String name = 'Alice';
  int age = 25;
  print('$name is $age years old');

  // Trim and padding
  String padded = '  Hello  ';
  print("Trimmed: '${padded.trim()}'");
  print("Padded: '${padded.padLeft(10)}'");

  // Reverse and palindrome
  String pal = 'racecar';
  String reversed = pal.split('').reversed.join('');
  print('$pal is palindrome: ${pal == reversed}');
}
Intermediate
25. What are Interfaces and Abstract Classes in Dart?

Interfaces and Abstract Classes define contracts for classes to implement, enabling polymorphism and code organization.

  • abstract class — blueprint for classes
  • implements — implement multiple interfaces
  • Interface Segregation: Focused interfaces
  • Default Implementation: Abstract classes with default methods
dart
// Interfaces and Abstract Classes
abstract class Drawable {
  void draw();
  void resize(double factor);
  double get area;
}

abstract class Shape implements Drawable {
  @override
  void draw();
  @override
  void resize(double factor);
  @override
  double get area;
}

class Circle extends Shape {
  double radius;

  Circle(this.radius);

  @override
  void draw() {
    print('Drawing Circle r=$radius');
  }

  @override
  void resize(double factor) {
    radius *= factor;
  }

  @override
  double get area => 3.14159 * radius * radius;
}

class Square extends Shape {
  double side;

  Square(this.side);

  @override
  void draw() {
    print('Drawing Square s=$side');
  }

  @override
  void resize(double factor) {
    side *= factor;
  }

  @override
  double get area => side * side;
}

void main() {
  List<Shape> shapes = [
    Circle(5.0),
    Square(4.0)
  ];

  for (var s in shapes) {
    s.draw();
    print('Area: ${s.area.toStringAsFixed(2)}');
    s.resize(2.0);
    s.draw();
    print('New Area: ${s.area.toStringAsFixed(2)}');
  }
}
Intermediate
26. How does Multiple Inheritance work via Mixins in Dart?

Mixins provide a way to reuse code across class hierarchies without multiple inheritance, offering flexible composition.

  • mixin — reusable code block
  • with — apply mixin to class
  • Composition: Combine multiple behaviors
  • Method Resolution: Mixin order matters
dart
// Multiple Inheritance via Mixins
mixin Vehicle {
  int speed = 0;
  void move();
}

mixin Electric {
  int battery = 0;
  void charge();
}

class ElectricCar with Vehicle, Electric {
  String model;

  ElectricCar(this.model, int speed, int battery) {
    this.speed = speed;
    this.battery = battery;
  }

  void display() {
    print('Model: $model');
    print('Speed: $speed km/h');
    print('Battery: $battery%');
  }

  @override
  void move() {
    print('$model glides silently at $speed km/h');
  }

  @override
  void charge() {
    print('Charging battery: $battery%');
  }
}

void main() {
  ElectricCar tesla = ElectricCar('Tesla Model 3', 250, 85);
  tesla.display();
  tesla.move();
  tesla.charge();
}
Intermediate
27. What are Extension Methods in Dart?

Extension Methods allow adding new functionality to existing types without modifying their source code, enhancing code readability.

  • extension — define extension
  • Method Chaining: Fluent interface design
  • Type Extension: Add methods to any type
  • Generic Extensions: Work with generic types
dart
// Extension Methods
extension StringExtensions on String {
  bool isPalindrome() {
    String cleaned = replaceAll(RegExp(r'[^a-zA-Z0-9]'), '').toLowerCase();
    return cleaned == cleaned.split('').reversed.join('');
  }

  String toTitleCase() {
    return this[0].toUpperCase() + substring(1).toLowerCase();
  }
}

extension ListExtensions<T> on List<T> {
  T second() {
    if (length < 2) throw StateError('List has less than 2 elements');
    return this[1];
  }

  T lastOrDefault(T defaultValue) {
    return isEmpty ? defaultValue : last;
  }
}

void main() {
  // Extension methods on strings
  String text = 'racecar';
  print('$text is palindrome: ${text.isPalindrome()}');

  String name = 'alice';
  print('Title case: ${name.toTitleCase()}');

  // Extension methods on lists
  List<int> numbers = [10, 20, 30, 40];
  print('Second: ${numbers.second()}');
  print('LastOrDefault(100): ${numbers.lastOrDefault(100)}');

  List<int> empty = [];
  print('Empty LastOrDefault: ${empty.lastOrDefault(100)}');

  // Chaining
  var result = numbers.where((x) => x > 15).map((x) => x * 2).toList();
  print('Chained: ${result.join(', ')}');
}
Advanced
28. What are Design Patterns - Singleton and Factory?

Singleton ensures a class has only one instance. Factory provides an interface for creating objects without specifying concrete classes.

  • Singleton: Global instance access
  • Factory: Object creation encapsulation
  • Lazy Initialization: Create on demand
  • Abstract Factory: Family of related objects
dart
// Design Patterns - Singleton and Factory
// Singleton
class Config {
  static final Config _instance = Config._internal();
  factory Config() => _instance;

  String _dbUrl = 'localhost:5432';

  Config._internal();

  String get dbUrl => _dbUrl;
  set dbUrl(String value) => _dbUrl = value;
}

// Factory Pattern
abstract class Logger {
  void log(String message);
}

class ConsoleLogger implements Logger {
  @override
  void log(String message) {
    print('[CONSOLE] $message');
  }
}

class FileLogger implements Logger {
  @override
  void log(String message) {
    print('[FILE] $message');
  }
}

Logger createLogger(String type) {
  switch (type.toLowerCase()) {
    case 'console':
      return ConsoleLogger();
    case 'file':
      return FileLogger();
    default:
      throw ArgumentError('Unknown logger type: $type');
  }
}

void main() {
  Config cfg = Config();
  print(cfg.dbUrl);

  Logger logger = createLogger('console');
  logger.log('App started');

  Logger flog = createLogger('file');
  flog.log('Error occurred');
}
Advanced
29. How do Libraries and Imports work in Dart?

Libraries organize code into reusable modules. Imports allow using code from other libraries with proper visibility.

  • library — library declaration
  • import — bring in external code
  • export — expose library interface
  • Visibility Control: Private vs public
dart
// Libraries and Imports
library math_utils;

const double PI = 3.14159265358979;

class Geometry {
  static double circleArea(double r) => PI * r * r;
  static double rectArea(double w, double h) => w * h;
}

library advanced_math;

class Algebra {
  static double power(double base, int exp) {
    double result = 1;
    for (int i = 0; i < exp; i++) result *= base;
    return result;
  }
}

library physics;

const double G = 9.81;

class Mechanics {
  static double kineticEnergy(double m, double v) => 0.5 * m * v * v;
  static double weight(double mass) => mass * G;
}

void main() {
  // Using the libraries
  print('PI = $PI');
  print('Circle area = ${Geometry.circleArea(5.0)}');
  print('2^8 = ${Algebra.power(2, 8)}');
  print('Weight(70kg) = ${Mechanics.weight(70)} N');

  // Using alias
  print('Rect area = ${Geometry.rectArea(4, 5)}');
}
Advanced
30. How do you solve the Two Sum Problem in Dart?

Two Sum is a classic algorithm problem that finds pairs in an array that sum to a target value using hash maps or two-pointer technique.

  • Hash Map Approach: O(n) time, O(n) space
  • Two Pointer: O(n log n) with sorting
  • Trade-offs: Time vs Space
  • Edge Cases: Duplicates, unsorted input
dart
// Two Sum Problem in Dart
// Hash map approach O(n)
List<int> twoSum(List<int> nums, int target) {
  Map<int, int> map = {};
  for (int i = 0; i < nums.length; i++) {
    int complement = target - nums[i];
    if (map.containsKey(complement)) {
      return [map[complement]!, i];
    }
    map[nums[i]] = i;
  }
  return [];
}

// Two pointer (sorted input)
List<(int, int)> twoSumPairs(List<int> arr, int target) {
  List<(int, int)> result = [];
  int l = 0, r = arr.length - 1;
  while (l < r) {
    int sum = arr[l] + arr[r];
    if (sum == target) {
      result.add((arr[l], arr[r]));
      l++;
      r--;
    } else if (sum < target) {
      l++;
    } else {
      r--;
    }
  }
  return result;
}

void main() {
  List<int> nums = [2, 7, 11, 15];
  List<int> res = twoSum(nums, 9);
  print('Indices: [${res[0]}, ${res[1]}]');

  List<int> sorted = [1, 2, 3, 4, 6];
  for (var pair in twoSumPairs(sorted, 6)) {
    print('Pair: ${pair.$1} + ${pair.$2}');
  }
}
Advanced
31. What is Kadane's Algorithm in Dart?

Kadane's Algorithm finds the maximum subarray sum in O(n) time, using dynamic programming to track current and maximum sums.

  • Dynamic Programming: Track current max
  • O(n) Time: Single pass algorithm
  • Negative Numbers: Handle all-negative arrays
  • Subarray Tracking: Find start and end indices
dart
// Kadane's Algorithm in Dart
(int, int, int) maxSubarray(List<int> arr) {
  int maxSum = -9223372036854775808;
  int currSum = 0;
  int start = 0, end = 0, tempStart = 0;

  for (int i = 0; i < arr.length; i++) {
    currSum += arr[i];
    if (currSum > maxSum) {
      maxSum = currSum;
      start = tempStart;
      end = i;
    }
    if (currSum < 0) {
      currSum = 0;
      tempStart = i + 1;
    }
  }
  return (maxSum, start, end);
}

void main() {
  List<int> arr = [-2, 1, -3, 4, -1, 2, 1, -5, 4];
  var (sum, s, e) = maxSubarray(arr);

  print('Max Sum: $sum');
  print('Subarray: ${arr.sublist(s, e + 1).join(' ')}');
}
Advanced
32. How do you implement a Binary Tree in Dart?

Binary Tree is a hierarchical data structure where each node has at most two children, enabling efficient search and traversal.

  • Node Structure: Value, left, right
  • Tree Traversal: Inorder, Preorder, Postorder
  • Insertion: Level-order insertion
  • Height Calculation: Recursive depth measurement
dart
// Binary Tree in Dart
class TreeNode<T> {
  T val;
  TreeNode<T>? left;
  TreeNode<T>? right;

  TreeNode(this.val) : left = null, right = null;
}

class BinaryTree<T> {
  TreeNode<T>? root;

  void insert(T val) {
    TreeNode<T> node = TreeNode<T>(val);
    if (root == null) {
      root = node;
      return;
    }
    List<TreeNode<T>> queue = [root!];
    while (queue.isNotEmpty) {
      TreeNode<T> curr = queue.removeAt(0);
      if (curr.left == null) {
        curr.left = node;
        return;
      } else {
        queue.add(curr.left!);
      }
      if (curr.right == null) {
        curr.right = node;
        return;
      } else {
        queue.add(curr.right!);
      }
    }
  }

  void inorder() {
    _inorder(root);
    print('');
  }

  void _inorder(TreeNode<T>? node) {
    if (node == null) return;
    _inorder(node.left);
    print('${node.val} ');
    _inorder(node.right);
  }

  int height() {
    return _height(root);
  }

  int _height(TreeNode<T>? node) {
    if (node == null) return 0;
    return 1 + (_height(node.left) > _height(node.right) 
        ? _height(node.left) 
        : _height(node.right));
  }
}

void main() {
  BinaryTree<int> bt = BinaryTree<int>();
  for (int v in [1, 2, 3, 4, 5, 6, 7]) {
    bt.insert(v);
  }
  bt.inorder();
  print('Height: ${bt.height()}');
}
Advanced
33. How do you implement a Binary Search Tree in Dart?

Binary Search Tree (BST) maintains sorted order with O(log n) average time for search, insert, and delete operations.

  • BST Property: Left < parent < right
  • Insertion: Recursive placement
  • Search: Binary search on tree
  • Traversal: Inorder gives sorted order
dart
// Binary Search Tree in Dart
class BST {
  int val;
  BST? left;
  BST? right;

  BST(this.val) : left = null, right = null;
}

BST? insert(BST? root, int val) {
  if (root == null) return BST(val);
  if (val < root.val) {
    root.left = insert(root.left, val);
  } else if (val > root.val) {
    root.right = insert(root.right, val);
  }
  return root;
}

bool search(BST? root, int val) {
  if (root == null) return false;
  if (root.val == val) return true;
  return val < root.val ? search(root.left, val) : search(root.right, val);
}

void inorder(BST? root) {
  if (root == null) return;
  inorder(root.left);
  print('${root.val} ');
  inorder(root.right);
}

void main() {
  BST? root = null;
  for (int v in [50, 30, 70, 20, 40, 60, 80]) {
    root = insert(root, v);
  }

  inorder(root);
  print('');
  print('Search 40: ${search(root, 40) ? 'Found' : 'Not found'}');
  print('Search 99: ${search(root, 99) ? 'Found' : 'Not found'}');
}
Advanced
34. How do Graph BFS and DFS work in Dart?

BFS (Breadth-First Search) explores level by level. DFS (Depth-First Search) explores as far as possible before backtracking.

  • BFS: Queue-based level-order traversal
  • DFS: Stack/recursive depth traversal
  • Visited Tracking: Prevent infinite loops
  • Applications: Shortest path, connected components
dart
// Graph BFS and DFS in Dart
class Graph {
  int v;
  List<List<int>> adj;

  Graph(this.v) : adj = List.generate(v, (_) => []);

  void addEdge(int u, int v) {
    adj[u].add(v);
    adj[v].add(u);
  }

  void bfs(int start) {
    List<bool> visited = List.filled(v, false);
    List<int> queue = [];
    visited[start] = true;
    queue.add(start);
    print('BFS: ');
    while (queue.isNotEmpty) {
      int v = queue.removeAt(0);
      print('$v ');
      for (int u in adj[v]) {
        if (!visited[u]) {
          visited[u] = true;
          queue.add(u);
        }
      }
    }
    print('');
  }

  void dfs(int start) {
    List<bool> visited = List.filled(v, false);
    print('DFS: ');
    _dfsHelper(start, visited);
    print('');
  }

  void _dfsHelper(int v, List<bool> visited) {
    visited[v] = true;
    print('$v ');
    for (int u in adj[v]) {
      if (!visited[u]) _dfsHelper(u, visited);
    }
  }
}

void main() {
  Graph g = Graph(6);
  g.addEdge(0, 1);
  g.addEdge(0, 2);
  g.addEdge(1, 3);
  g.addEdge(2, 4);
  g.addEdge(3, 5);
  g.bfs(0);
  g.dfs(0);
}
Advanced
35. How does Dijkstra's Algorithm work in Dart?

Dijkstra's Algorithm finds the shortest path from a source to all vertices in a weighted graph with non-negative edges.

  • Shortest Path: Single source, all destinations
  • Priority Queue: Efficient minimum selection
  • Edge Relaxation: Update distances
  • Limitations: No negative edges
dart
// Dijkstra's Algorithm in Dart
import 'dart:collection';

void dijkstra(List<List<(int, int)>> graph, int src) {
  int v = graph.length;
  List<int> dist = List.filled(v, 9223372036854775807);
  List<bool> visited = List.filled(v, false);
  dist[src] = 0;

  for (int i = 0; i < v; i++) {
    // Find minimum distance vertex
    int minDist = 9223372036854775807;
    int minVertex = -1;
    for (int j = 0; j < v; j++) {
      if (!visited[j] && dist[j] < minDist) {
        minDist = dist[j];
        minVertex = j;
      }
    }
    if (minVertex == -1) break;

    visited[minVertex] = true;
    for (var (w, neighbor) in graph[minVertex]) {
      if (!visited[neighbor] && dist[minVertex] + w < dist[neighbor]) {
        dist[neighbor] = dist[minVertex] + w;
      }
    }
  }

  print('Shortest distances from $src:');
  for (int i = 0; i < v; i++) {
    print('  To $i: ${dist[i] == 9223372036854775807 ? -1 : dist[i]}');
  }
}

void main() {
  int v = 5;
  List<List<(int, int)>> graph = List.generate(v, (_) => []);

  void addEdge(int u, int v, int w) {
    graph[u].add((w, v));
    graph[v].add((w, u));
  }

  addEdge(0, 1, 10);
  addEdge(0, 3, 5);
  addEdge(1, 2, 1);
  addEdge(1, 3, 2);
  addEdge(2, 4, 4);
  addEdge(3, 4, 9);

  dijkstra(graph, 0);
}
Advanced
36. What are Dynamic Programming problems like Knapsack and LCS?

Dynamic Programming solves optimization problems by breaking them into overlapping subproblems and storing results.

  • 0/1 Knapsack: Maximize value with weight constraint
  • LCS: Longest Common Subsequence
  • Optimal Substructure: Build from subproblems
  • Memoization: Cache computed results
dart
// Dynamic Programming - Classic Problems
// 0/1 Knapsack
int knapsack(List<int> weights, List<int> values, int w) {
  int n = weights.length;
  List<List<int>> dp = List.generate(n + 1, (_) => List.filled(w + 1, 0));
  for (int i = 1; i <= n; i++) {
    for (int j = 0; j <= w; j++) {
      dp[i][j] = dp[i - 1][j];
      if (weights[i - 1] <= j) {
        int val = dp[i - 1][j - weights[i - 1]] + values[i - 1];
        if (val > dp[i][j]) dp[i][j] = val;
      }
    }
  }
  return dp[n][w];
}

// Longest Common Subsequence
int lcs(String s1, String s2) {
  int m = s1.length, n = s2.length;
  List<List<int>> dp = List.generate(m + 1, (_) => List.filled(n + 1, 0));
  for (int i = 1; i <= m; i++) {
    for (int j = 1; j <= n; j++) {
      if (s1[i - 1] == s2[j - 1]) {
        dp[i][j] = dp[i - 1][j - 1] + 1;
      } else {
        dp[i][j] = dp[i - 1][j] > dp[i][j - 1] ? dp[i - 1][j] : dp[i][j - 1];
      }
    }
  }
  return dp[m][n];
}

void main() {
  List<int> weights = [1, 3, 4, 5];
  List<int> values = [1, 4, 5, 7];
  print('Knapsack(W=7): ${knapsack(weights, values, 7)}');

  String s1 = 'ABCBDAB';
  String s2 = 'BDCAB';
  print('LCS: ${lcs(s1, s2)}');
}
Advanced
37. How do you implement a custom Hash Map in Dart?

Hash Map implementation involves creating buckets, handling collisions, and providing efficient key-value operations.

  • Hash Function: Map keys to bucket indices
  • Collision Handling: Chaining with lists
  • Operations: Put, Get, Remove
  • Load Factor: Performance optimization
dart
// Hash Map - Custom Implementation
class HashMap<K, V> {
  int capacity;
  List<List<MapEntry<K, V>>> table;

  HashMap({this.capacity = 16}) 
      : table = List.generate(16, (_) => []);

  int _hash(K key) {
    return key.hashCode.abs() % capacity;
  }

  void put(K key, V value) {
    int idx = _hash(key);
    for (int i = 0; i < table[idx].length; i++) {
      if (table[idx][i].key == key) {
        table[idx][i] = MapEntry(key, value);
        return;
      }
    }
    table[idx].add(MapEntry(key, value));
  }

  V get(K key) {
    int idx = _hash(key);
    for (var entry in table[idx]) {
      if (entry.key == key) return entry.value;
    }
    throw Exception('Key not found');
  }

  bool containsKey(K key) {
    int idx = _hash(key);
    for (var entry in table[idx]) {
      if (entry.key == key) return true;
    }
    return false;
  }

  void remove(K key) {
    int idx = _hash(key);
    table[idx].removeWhere((entry) => entry.key == key);
  }
}

void main() {
  HashMap<String, int> map = HashMap<String, int>();
  map.put('alice', 90);
  map.put('bob', 85);
  map.put('carol', 92);
  print('alice: ${map.get('alice')}');
  print('Contains bob: ${map.containsKey('bob')}');
  map.remove('bob');
  print('Contains bob after remove: ${map.containsKey('bob')}');
}
Advanced
38. What are Heap and Priority Queue in Dart?

Heap and Priority Queue provide efficient priority-based operations with O(log n) insertion and removal.

  • Min-Heap/Max-Heap: Priority ordering
  • K-Largest Elements: Heap-based selection
  • Merge Sorted Arrays: Efficient merging
  • Custom Comparators: Flexible ordering
dart
// Heap and Priority Queue in Dart
import 'dart:collection';

// K largest elements
List<int> kLargest(List<int> arr, int k) {
  PriorityQueue<int> minHeap = PriorityQueue<int>((a, b) => a.compareTo(b));
  for (int x in arr) {
    minHeap.add(x);
    if (minHeap.length > k) minHeap.removeFirst();
  }
  return minHeap.toList();
}

// Merge K sorted arrays
List<int> mergeKSorted(List<List<int>> arrays) {
  PriorityQueue<(int, int, int)> pq = PriorityQueue<(int, int, int)>(
    (a, b) => a.$1.compareTo(b.$1)
  );
  for (int i = 0; i < arrays.length; i++) {
    if (arrays[i].isNotEmpty) {
      pq.add((arrays[i][0], i, 0));
    }
  }

  List<int> result = [];
  while (pq.isNotEmpty) {
    var (val, i, j) = pq.removeFirst();
    result.add(val);
    if (j + 1 < arrays[i].length) {
      pq.add((arrays[i][j + 1], i, j + 1));
    }
  }
  return result;
}

void main() {
  List<int> arr = [3, 1, 5, 12, 2, 11, 9];
  List<int> top3 = kLargest(arr, 3);
  print('Top 3: ${top3.join(' ')}');

  List<List<int>> kArr = [
    [1, 4, 7],
    [2, 5, 8],
    [3, 6, 9]
  ];
  List<int> merged = mergeKSorted(kArr);
  print('Merged: ${merged.join(' ')}');
}
Advanced
39. How does a Trie Data Structure work in Dart?

Trie (Prefix Tree) enables efficient prefix-based operations like autocomplete, dictionary search, and pattern matching.

  • Node Structure: Children map, end marker
  • Insertion: Build tree character by character
  • Search: Exact word or prefix
  • Applications: Autocomplete, spell checking
dart
// Trie Data Structure in Dart
class TrieNode {
  Map<String, TrieNode> children = {};
  bool isEnd = false;
}

class Trie {
  TrieNode root = TrieNode();

  void insert(String word) {
    TrieNode curr = root;
    for (String c in word.split('')) {
      if (!curr.children.containsKey(c)) {
        curr.children[c] = TrieNode();
      }
      curr = curr.children[c]!;
    }
    curr.isEnd = true;
  }

  bool search(String word) {
    TrieNode curr = root;
    for (String c in word.split('')) {
      if (!curr.children.containsKey(c)) return false;
      curr = curr.children[c]!;
    }
    return curr.isEnd;
  }

  bool startsWith(String prefix) {
    TrieNode curr = root;
    for (String c in prefix.split('')) {
      if (!curr.children.containsKey(c)) return false;
      curr = curr.children[c]!;
    }
    return true;
  }
}

void main() {
  Trie t = Trie();
  t.insert('apple');
  t.insert('app');
  t.insert('apply');
  print('Search apple: ${t.search('apple')}');
  print('Search app: ${t.search('app')}');
  print('Search ap: ${t.search('ap')}');
  print('StartsWith appl: ${t.startsWith('appl')}');
  print('StartsWith xyz: ${t.startsWith('xyz')}');
}
Advanced
40. How do you implement a Segment Tree in Dart?

Segment Tree efficiently answers range queries and supports point updates on arrays with O(log n) time complexity.

  • Range Queries: Sum, min, max
  • Point Updates: Modify single element
  • Build Time: O(n) construction
  • Applications: RMQ, prefix sums
dart
// Segment Tree in Dart
class SegmentTree {
  List<int> tree;
  int n;

  SegmentTree(List<int> arr) 
      : n = arr.length,
        tree = List.filled(4 * arr.length, 0) {
    _build(arr, 1, 0, n - 1);
  }

  void _build(List<int> arr, int node, int l, int r) {
    if (l == r) {
      tree[node] = arr[l];
      return;
    }
    int mid = (l + r) ~/ 2;
    _build(arr, node * 2, l, mid);
    _build(arr, node * 2 + 1, mid + 1, r);
    tree[node] = tree[node * 2] + tree[node * 2 + 1];
  }

  void update(int idx, int val) {
    _update(1, 0, n - 1, idx, val);
  }

  void _update(int node, int l, int r, int idx, int val) {
    if (l == r) {
      tree[node] = val;
      return;
    }
    int mid = (l + r) ~/ 2;
    if (idx <= mid) {
      _update(node * 2, l, mid, idx, val);
    } else {
      _update(node * 2 + 1, mid + 1, r, idx, val);
    }
    tree[node] = tree[node * 2] + tree[node * 2 + 1];
  }

  int query(int ql, int qr) {
    return _query(1, 0, n - 1, ql, qr);
  }

  int _query(int node, int l, int r, int ql, int qr) {
    if (qr < l || r < ql) return 0;
    if (ql <= l && r <= qr) return tree[node];
    int mid = (l + r) ~/ 2;
    return _query(node * 2, l, mid, ql, qr) +
           _query(node * 2 + 1, mid + 1, r, ql, qr);
  }
}

void main() {
  List<int> arr = [1, 3, 5, 7, 9, 11];
  SegmentTree st = SegmentTree(arr);
  print('Sum [1,3]: ${st.query(1, 3)}');
  st.update(1, 10);
  print('Sum [1,3] after update: ${st.query(1, 3)}');
}
Advanced
41. How does Union-Find (Disjoint Set) work in Dart?

Union-Find efficiently manages disjoint sets with union and find operations, using path compression and union by rank.

  • Find Operation: Locate set representative
  • Union Operation: Merge two sets
  • Path Compression: Optimize find
  • Union by Rank: Efficient merging
dart
// Union-Find in Dart
class UnionFind {
  List<int> parent;
  List<int> rank;

  UnionFind(int n) 
      : parent = List.generate(n, (i) => i),
        rank = List.filled(n, 0);

  int find(int x) {
    if (parent[x] != x) {
      parent[x] = find(parent[x]);
    }
    return parent[x];
  }

  bool unite(int x, int y) {
    int px = find(x);
    int py = find(y);
    if (px == py) return false;
    if (rank[px] < rank[py]) {
      int temp = px;
      px = py;
      py = temp;
    }
    parent[py] = px;
    if (rank[px] == rank[py]) rank[px]++;
    return true;
  }

  bool connected(int x, int y) {
    return find(x) == find(y);
  }
}

void main() {
  UnionFind uf = UnionFind(6);
  uf.unite(0, 1);
  uf.unite(1, 2);
  uf.unite(3, 4);
  print('0-2: ${uf.connected(0, 2)}');
  print('0-3: ${uf.connected(0, 3)}');
  uf.unite(2, 3);
  print('0-4 after merge: ${uf.connected(0, 4)}');
}
Advanced
42. What is Sliding Window Maximum in Dart?

Sliding Window Maximum finds the maximum in each sliding window of size k using a deque for efficient processing.

  • Deque Approach: O(n) time complexity
  • Window Tracking: Maintain indices
  • Remove Out-of-Window: Keep valid elements
  • Applications: Streaming data, time-series
dart
// Sliding Window Maximum in Dart
List<int> maxSlidingWindow(List<int> nums, int k) {
  List<int> deque = [];
  List<int> result = [];

  for (int i = 0; i < nums.length; i++) {
    // Remove out-of-window indices
    while (deque.isNotEmpty && deque.first < i - k + 1) {
      deque.removeAt(0);
    }

    // Remove smaller elements from rear
    while (deque.isNotEmpty && nums[deque.last] < nums[i]) {
      deque.removeLast();
    }

    deque.add(i);

    if (i >= k - 1) {
      result.add(nums[deque.first]);
    }
  }
  return result;
}

void main() {
  List<int> nums = [1, 3, -1, -3, 5, 3, 6, 7];
  int k = 3;
  List<int> res = maxSlidingWindow(nums, k);
  print('Sliding window max: ${res.join(' ')}');
}
Advanced
43. How does KMP String Matching work in Dart?

KMP (Knuth-Morris-Pratt) is an efficient string matching algorithm using a partial match table to avoid unnecessary comparisons.

  • LPS Array: Longest proper prefix suffix
  • Pattern Preprocessing: Build LPS table
  • Efficient Search: O(n) time complexity
  • Applications: Pattern matching, text search
dart
// KMP String Matching in Dart
List<int> buildLPS(String pattern) {
  int m = pattern.length;
  List<int> lps = List.filled(m, 0);
  int len = 0;
  int i = 1;
  while (i < m) {
    if (pattern[i] == pattern[len]) {
      lps[i++] = ++len;
    } else if (len > 0) {
      len = lps[len - 1];
    } else {
      lps[i++] = 0;
    }
  }
  return lps;
}

List<int> kmpSearch(String text, String pattern) {
  List<int> positions = [];
  List<int> lps = buildLPS(pattern);
  int n = text.length;
  int m = pattern.length;
  int i = 0, j = 0;

  while (i < n) {
    if (text[i] == pattern[j]) {
      i++;
      j++;
    }
    if (j == m) {
      positions.add(i - j);
      j = lps[j - 1];
    } else if (i < n && text[i] != pattern[j]) {
      if (j > 0) {
        j = lps[j - 1];
      } else {
        i++;
      }
    }
  }
  return positions;
}

void main() {
  String text = 'AABAACAADAABAABA';
  String pat = 'AABA';
  List<int> pos = kmpSearch(text, pat);
  print('Pattern found at: ${pos.join(' ')}');
}
Advanced
44. How do you solve the N-Queens problem in Dart?

N-Queens is a classic backtracking problem that places N queens on an N×N chessboard where no two queens attack each other.

  • Backtracking: Systematic trial and error
  • Column Placement: One queen per column
  • Safety Check: Row and diagonal conflicts
  • Solution Counting: Total valid configurations
dart
// N-Queens in Dart
class NQueens {
  int n;
  List<List<int>> board;
  int solutions = 0;

  NQueens(this.n) : board = List.generate(n, (_) => List.filled(n, 0));

  bool isSafe(int row, int col) {
    for (int j = 0; j < col; j++) {
      if (board[row][j] == 1) return false;
    }
    for (int i = row, j = col; i >= 0 && j >= 0; i--, j--) {
      if (board[i][j] == 1) return false;
    }
    for (int i = row, j = col; i < n && j >= 0; i++, j--) {
      if (board[i][j] == 1) return false;
    }
    return true;
  }

  void solve(int col) {
    if (col == n) {
      solutions++;
      if (solutions == 1) {
        for (var row in board) {
          print(row.map((x) => x == 1 ? 'Q' : '.').join(' '));
        }
      }
      return;
    }
    for (int row = 0; row < n; row++) {
      if (isSafe(row, col)) {
        board[row][col] = 1;
        solve(col + 1);
        board[row][col] = 0;
      }
    }
  }

  void run() {
    solve(0);
    print('Total solutions: $solutions');
  }
}

void main() {
  NQueens q = NQueens(8);
  q.run();
}
Advanced
45. How does LRU Cache work in Dart?

LRU Cache (Least Recently Used) maintains a fixed-size cache, evicting the least recently used items when capacity is exceeded.

  • LinkedHashMap: Maintains insertion order
  • Get Operation: Access moves to most recent
  • Put Operation: Update or add with eviction
  • Cache Management: Capacity and eviction policy
dart
// LRU Cache in Dart
class LRUCache<K, V> {
  int capacity;
  LinkedHashMap<K, V> cache;

  LRUCache(this.capacity) : cache = LinkedHashMap<K, V>();

  V? get(K key) {
    if (!cache.containsKey(key)) return null;
    V value = cache.remove(key)!;
    cache[key] = value;
    return value;
  }

  void put(K key, V value) {
    if (cache.containsKey(key)) {
      cache.remove(key);
    }
    if (cache.length == capacity) {
      cache.remove(cache.keys.first);
    }
    cache[key] = value;
  }
}

void main() {
  LRUCache<int, int> lru = LRUCache<int, int>(2);
  lru.put(1, 10);
  lru.put(2, 20);
  print(lru.get(1));
  lru.put(3, 30);
  print(lru.get(2));
  print(lru.get(3));
}
Advanced
46. How does Topological Sort work in Dart?

Topological Sort orders vertices in a directed acyclic graph (DAG) such that for every edge u→v, u comes before v.

  • Kahn's Algorithm: Queue-based approach
  • Indegree Tracking: Count incoming edges
  • Applications: Task scheduling, dependency resolution
  • Cycle Detection: DAG verification
dart
// Graph - Topological Sort in Dart
List<int> topoSort(int v, List<List<int>> adj) {
  List<int> inDegree = List.filled(v, 0);
  for (int u = 0; u < v; u++) {
    for (int node in adj[u]) {
      inDegree[node]++;
    }
  }

  List<int> queue = [];
  for (int i = 0; i < v; i++) {
    if (inDegree[i] == 0) queue.add(i);
  }

  List<int> order = [];
  while (queue.isNotEmpty) {
    int u = queue.removeAt(0);
    order.add(u);
    for (int node in adj[u]) {
      if (--inDegree[node] == 0) {
        queue.add(node);
      }
    }
  }

  return order.length == v ? order : [];
}

void main() {
  int v = 6;
  List<List<int>> adj = List.generate(v, (_) => []);

  adj[5].add(2);
  adj[5].add(0);
  adj[4].add(0);
  adj[4].add(1);
  adj[2].add(3);
  adj[3].add(1);

  List<int> order = topoSort(v, adj);
  print('Topological Order: ${order.join(' ')}');
}
Advanced
47. What is Bit Manipulation in Dart?

Bit Manipulation uses bitwise operations for efficient programming, including checking, setting, and toggling bits.

  • Bitwise Operators: &, |, ^, ~, <<, >>
  • Bit Checking: Test if bit is set
  • Counting Bits: Efficient population count
  • Power of 2: Check using bit magic
dart
// Bit Manipulation in Dart
bool isBitSet(int n, int p) => (n >> p) & 1 == 1;
int setBit(int n, int p) => n | (1 << p);
int clearBit(int n, int p) => n & ~(1 << p);
int toggleBit(int n, int p) => n ^ (1 << p);

int countBits(int n) {
  int count = 0;
  while (n > 0) {
    n &= n - 1;
    count++;
  }
  return count;
}

bool isPowerOf2(int n) => n > 0 && (n & (n - 1)) == 0;

// Find unique (all others appear twice)
int findUnique(List<int> arr) {
  int result = 0;
  for (int x in arr) result ^= x;
  return result;
}

void main() {
  int n = 0b10110100;
  print('Number: $n');
  print('Bit 2 set? ${isBitSet(n, 2)}');
  print('Set bit 0: ${setBit(n, 0)}');
  print('Clear bit 4: ${clearBit(n, 4)}');
  print('Toggle bit 7: ${toggleBit(n, 7)}');
  print('Count bits: ${countBits(n)}');
  print('isPow2(16): ${isPowerOf2(16)}');

  List<int> arr = [2, 3, 5, 4, 5, 3, 4];
  print('Unique: ${findUnique(arr)}');
}
Advanced
48. What is Number Theory in Dart?

Number Theory includes algorithms for GCD, LCM, prime numbers, sieve, and modular exponentiation.

  • GCD/LCM: Euclidean algorithm
  • Prime Detection: Trial division, sieve
  • Modular Arithmetic: Modular exponentiation
  • Applications: Cryptography, number theory
dart
// Number Theory in Dart
int gcd(int a, int b) => b == 0 ? a : gcd(b, a % b);
int lcm(int a, int b) => a ~/ gcd(a, b) * b;

bool isPrime(int n) {
  if (n < 2) return false;
  for (int i = 2; i * i <= n; i++) {
    if (n % i == 0) return false;
  }
  return true;
}

List<int> sieve(int limit) {
  List<bool> notPrime = List.filled(limit + 1, false);
  if (limit >= 0) notPrime[0] = true;
  if (limit >= 1) notPrime[1] = true;
  for (int i = 2; i * i <= limit; i++) {
    if (!notPrime[i]) {
      for (int j = i * i; j <= limit; j += i) {
        notPrime[j] = true;
      }
    }
  }
  List<int> primes = [];
  for (int i = 2; i <= limit; i++) {
    if (!notPrime[i]) primes.add(i);
  }
  return primes;
}

int modPow(int base, int exp, int mod) {
  int result = 1;
  base %= mod;
  while (exp > 0) {
    if (exp.isOdd) result = (result * base) % mod;
    base = (base * base) % mod;
    exp >>= 1;
  }
  return result;
}

void main() {
  print('GCD(48,18)=${gcd(48, 18)}');
  print('LCM(4,6)=${lcm(4, 6)}');
  print('isPrime(17)=${isPrime(17)}');

  List<int> primes = sieve(50);
  print('Primes: ${primes.join(' ')}');

  print('2^10 mod 1000 = ${modPow(2, 10, 1000)}');
}
Advanced
49. How do Tuples (Records) work in Dart?

Records (tuples) provide a way to group multiple values into a single object with positional or named fields.

  • Positional Records: Access by index
  • Named Records: Access by field name
  • Deconstruction: Pattern matching
  • Return Values: Multiple return values
dart
// Tuples in Dart (using Records)
void main() {
  // Record (tuple)
  var t1 = ('Alice', 25, 3.85);
  print('${t1.$1} age=${t1.$2} gpa=${t1.$3}');

  // Named record
  var t2 = (name: 'Bob', age: 22, gpa: 3.62);
  print('${t2.name} age=${t2.age} gpa=${t2.gpa}');

  // Record deconstruction
  var (n, a, g) = t1;
  print('Deconstructed: $n, $a, $g');

  // Named record in method return
  (int min, int max) getMinMax(List<int> nums) {
    int min = nums.reduce((a, b) => a < b ? a : b);
    int max = nums.reduce((a, b) => a > b ? a : b);
    return (min, max);
  }

  var result = getMinMax([5, 2, 8, 1, 9]);
  print('Min=${result.min}, Max=${result.max}');

  // Records in collections
  List<(String, int)> students = [
    ('Alice', 90),
    ('Bob', 85),
    ('Carol', 92)
  ];
  students.sort((a, b) => b.$2.compareTo(a.$2));
  for (var (name, score) in students) {
    print('$name: $score');
  }
}
Advanced
50. What is the Two Pointers Technique in Dart?

Two Pointers technique efficiently solves array problems like container with most water and three-sum using two converging pointers.

  • Container with Most Water: Maximize area
  • Three-Sum: Find triplets summing to zero
  • Pointer Movement: Conditional advancement
  • Applications: Array problems, palindrome checking
dart
// Two Pointers Technique in Dart
// Container with most water
int maxWater(List<int> height) {
  int l = 0, r = height.length - 1, maxArea = 0;
  while (l < r) {
    int area = (height[l] < height[r] ? height[l] : height[r]) * (r - l);
    if (area > maxArea) maxArea = area;
    if (height[l] < height[r]) {
      l++;
    } else {
      r--;
    }
  }
  return maxArea;
}

// 3-sum
List<List<int>> threeSum(List<int> nums) {
  nums.sort();
  List<List<int>> result = [];
  for (int i = 0; i < nums.length - 2; i++) {
    if (i > 0 && nums[i] == nums[i - 1]) continue;
    int l = i + 1, r = nums.length - 1;
    while (l < r) {
      int sum = nums[i] + nums[l] + nums[r];
      if (sum == 0) {
        result.add([nums[i], nums[l], nums[r]]);
        while (l < r && nums[l] == nums[l + 1]) l++;
        while (l < r && nums[r] == nums[r - 1]) r--;
        l++;
        r--;
      } else if (sum < 0) {
        l++;
      } else {
        r--;
      }
    }
  }
  return result;
}

void main() {
  List<int> h = [1, 8, 6, 2, 5, 4, 8, 3, 7];
  print('Max water: ${maxWater(h)}');

  List<int> nums = [-1, 0, 1, 2, -1, -4];
  for (var triplet in threeSum(nums)) {
    print(triplet.join(' '));
  }
}
Advanced
51. How does Backtracking work in Dart?

Backtracking is an algorithmic technique for solving problems by trying possibilities and undoing choices when they lead to dead ends.

  • Subset Generation: Generate all subsets
  • Permutations: All possible arrangements
  • State Management: Track current state
  • Applications: Combinatorial problems
dart
// Backtracking in Dart
// Generate all subsets
List<List<int>> subsets(List<int> nums) {
  List<List<int>> result = [];
  _backtrackSubsets(nums, 0, [], result);
  return result;
}

void _backtrackSubsets(List<int> nums, int idx, List<int> curr, List<List<int>> result) {
  result.add(List.from(curr));
  for (int i = idx; i < nums.length; i++) {
    curr.add(nums[i]);
    _backtrackSubsets(nums, i + 1, curr, result);
    curr.removeLast();
  }
}

// Generate permutations
List<List<int>> permute(List<int> nums) {
  List<List<int>> result = [];
  _permuteHelper(nums, 0, result);
  return result;
}

void _permuteHelper(List<int> nums, int start, List<List<int>> result) {
  if (start == nums.length) {
    result.add(List.from(nums));
    return;
  }
  for (int i = start; i < nums.length; i++) {
    _swap(nums, start, i);
    _permuteHelper(nums, start + 1, result);
    _swap(nums, start, i);
  }
}

void _swap(List<int> arr, int i, int j) {
  int temp = arr[i];
  arr[i] = arr[j];
  arr[j] = temp;
}

void main() {
  List<int> nums = [1, 2, 3];

  var subsetsResult = subsets(nums);
  print('Subsets (${subsetsResult.length}):');
  for (var s in subsetsResult) {
    print('[${s.join(' ')}]');
  }

  var perms = permute(nums);
  print('Permutations (${perms.length}):');
  for (var p in perms) {
    print(p.join(' '));
  }
}
Advanced
52. What are Greedy Algorithms in Dart?

Greedy Algorithms make locally optimal choices at each step to find a global optimum for certain problems.

  • Activity Selection: Maximize non-overlapping activities
  • Fractional Knapsack: Fractional item selection
  • Optimal Substructure: Greedy choice property
  • Applications: Scheduling, resource allocation
dart
// Greedy Algorithms in Dart
// Activity Selection
int activitySelection(List<(int, int)> activities) {
  activities.sort((a, b) => a.$2.compareTo(b.$2));
  int count = 1;
  int lastEnd = activities[0].$2;
  for (int i = 1; i < activities.length; i++) {
    if (activities[i].$1 >= lastEnd) {
      count++;
      lastEnd = activities[i].$2;
    }
  }
  return count;
}

// Fractional Knapsack
double fractionalKnapsack(List<(int, int)> items, int w) {
  items.sort((a, b) => (b.$1 / b.$2).compareTo(a.$1 / a.$2));
  double total = 0.0;
  for (var (value, weight) in items) {
    if (w >= weight) {
      total += value;
      w -= weight;
    } else {
      total += (value / weight) * w;
      break;
    }
  }
  return total;
}

void main() {
  List<(int, int)> acts = [
    (1, 3), (2, 5), (4, 6), (6, 8), (5, 7)
  ];
  print('Max activities: ${activitySelection(acts)}');

  List<(int, int)> items = [
    (60, 10), (100, 20), (120, 30)
  ];
  print('Max value (W=50): ${fractionalKnapsack(items, 50).toStringAsFixed(2)}');
}
Advanced
53. How do Events and Delegates work in Dart?

Events and Delegates implement the observer pattern, enabling loose coupling between components through event subscription and handling.

  • Event Handlers: Function delegates
  • Event Arguments: Carry event data
  • Subscription Management: Add/remove handlers
  • Observer Pattern: Push notifications
dart
// Events and Delegates in Dart
// Delegate definition
typedef PriceChangedEventHandler = void Function(Stock sender, PriceChangedEventArgs e);

// Event args
class PriceChangedEventArgs {
  final double oldPrice;
  final double newPrice;

  PriceChangedEventArgs(this.oldPrice, this.newPrice);
}

// Subject
class Stock {
  String symbol;
  double _price;
  List<PriceChangedEventHandler> _handlers = [];

  Stock(this.symbol, double price) : _price = price;

  double get price => _price;
  set price(double value) {
    if (_price == value) return;
    double old = _price;
    _price = value;
    _onPriceChanged(old, _price);
  }

  void addHandler(PriceChangedEventHandler handler) {
    _handlers.add(handler);
  }

  void removeHandler(PriceChangedEventHandler handler) {
    _handlers.remove(handler);
  }

  void _onPriceChanged(double oldPrice, double newPrice) {
    var args = PriceChangedEventArgs(oldPrice, newPrice);
    for (var handler in _handlers) {
      handler(this, args);
    }
  }
}

// Observer
class Investor {
  String name;

  Investor(this.name);

  void handlePriceChange(Stock sender, PriceChangedEventArgs e) {
    print('$name notified: Price changed from $${e.oldPrice} to $${e.newPrice}');
  }
}

void main() {
  Stock apple = Stock('AAPL', 150);
  Investor alice = Investor('Alice');
  Investor bob = Investor('Bob');

  apple.addHandler(alice.handlePriceChange);
  apple.addHandler(bob.handlePriceChange);

  apple.price = 155;
  apple.price = 160;
}
Advanced
54. How does Disposable and Resource Management work in Dart?

Disposable Pattern ensures proper cleanup of resources like file handles, database connections, and network sockets.

  • Resource Acquisition: Open/initialize resources
  • Resource Release: Close/cleanup properly
  • Try-Finally: Guaranteed cleanup
  • Using Pattern: RAII-style management
dart
// Disposable and Resource Management
class FileHandler {
  String filename;

  FileHandler(this.filename) {
    print('File opened: $filename');
  }

  void write(String data) {
    print('Writing: $data');
  }

  void dispose() {
    print('File closed: $filename');
  }
}

void main() {
  // Using try-finally for cleanup
  FileHandler fh = FileHandler('test.txt');
  try {
    fh.write('Hello RAII!');
    fh.write('Line 2');
  } finally {
    fh.dispose();
  }

  // Using a helper function
  void withFile(String name, void Function(FileHandler) action) {
    var handler = FileHandler(name);
    try {
      action(handler);
    } finally {
      handler.dispose();
    }
  }

  withFile('test2.txt', (fh) {
    fh.write('Data');
  });

  // Manual disposal
  FileHandler fh3 = FileHandler('test3.txt');
  try {
    fh3.write('Data');
  } finally {
    fh3.dispose();
  }
}
Advanced
55. How does Async and Parallel Programming work in Dart?

Async and Parallel programming uses isolates for true parallelism and async/await for non-blocking operations.

  • Isolates: Parallel execution units
  • Async/Await: Non-blocking operations
  • Task Parallelism: Parallel task execution
  • Cancellation: Using Completer
dart
// Async and Parallel Programming
import 'dart:async';
import 'dart:isolate';

void main() async {
  // Parallel processing with isolates
  List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  
  ReceivePort receivePort = ReceivePort();
  await for (var message in receivePort) {
    // Process results
  }

  // Async tasks
  List<Future<int>> tasks = [];
  for (int i = 0; i < 5; i++) {
    int num = i;
    tasks.add(Future.delayed(Duration(milliseconds: 100), () => num * num));
  }

  List<int> results = await Future.wait(tasks);
  print('Async results: ${results.join(', ')}');

  // Cancellation token (using Completer)
  Completer<bool> cancelCompleter = Completer<bool>();
  try {
    await Future.delayed(Duration(milliseconds: 500), () {
      if (!cancelCompleter.isCompleted) {
        throw Exception('Cancelled!');
      }
    });
  } catch (e) {
    print('Cancelled!');
  }
}
Advanced
56. What are Regular Expressions in Dart?

Regular Expressions provide powerful pattern matching for text validation, search, and replacement operations.

  • Pattern Matching: Validate input formats
  • Search/Replace: Text manipulation
  • Groups: Capture matched parts
  • Named Groups: Readable pattern parts
dart
// Regular Expressions in Dart
void main() {
  // Email validation
  RegExp emailRx = RegExp(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$');
  List<String> emails = ['user@example.com', 'invalid-email', 'hello@world.org'];
  for (String e in emails) {
    print('$e: ${emailRx.hasMatch(e) ? 'Valid' : 'Invalid'}');
  }

  // Search and replace
  String text = 'The quick brown fox jumps over the lazy dog';
  String replaced = text.replaceAllMapped(RegExp(r'w{4}'), (match) => '****');
  print('Replaced: $replaced');

  // Find all matches
  String data = 'Price: $100, Discount: $20, Total: $80';
  RegExp numRx = RegExp(r'$(d+)');
  Iterable<Match> matches = numRx.allMatches(data);
  print('Numbers found: ');
  for (var m in matches) {
    print('${m.group(1)} ');
  }
  print('');

  // Named groups
  RegExp dateRx = RegExp(r'(?<year>d{4})-(?<month>d{2})-(?<day>d{2})');
  Match? dateMatch = dateRx.firstMatch('2024-01-15');
  if (dateMatch != null) {
    print('Year: ${dateMatch.namedGroup('year')}');
    print('Month: ${dateMatch.namedGroup('month')}');
    print('Day: ${dateMatch.namedGroup('day')}');
  }

  // Capture groups
  RegExp wordRx = RegExp(r'(w+)s+(w+)');
  Match? match = wordRx.firstMatch('Hello World');
  if (match != null) {
    print('Word 1: ${match.group(1)}');
    print('Word 2: ${match.group(2)}');
  }
}
Advanced
57. What are Annotations and Reflection in Dart?

Annotations add metadata to code. Reflection enables runtime type inspection and dynamic method invocation.

  • Custom Annotations: Metadata on classes/methods
  • Mirrors: Reflection API
  • Runtime Type Info: Inspect at runtime
  • Dynamic Invocation: Call methods by name
dart
// Annotations and Reflection in Dart
import 'dart:mirrors';

class Author {
  final String name;
  final String version;

  const Author(this.name, {this.version = '1.0'});
}

@Author('John Doe')
class Calculator {
  @Author('Jane Smith', version: '2.0')
  int add(int a, int b) => a + b;

  int multiply(int a, int b) => a * b;
}

void main() {
  // Get class annotations
  ClassMirror classMirror = reflectClass(Calculator);
  var classAnnotations = classMirror.metadata;
  for (var annotation in classAnnotations) {
    if (annotation.reflectee is Author) {
      var author = annotation.reflectee as Author;
      print('Class Author: ${author.name} (v${author.version})');
    }
  }

  // Get method annotations
  InstanceMirror calcInstance = reflect(Calculator());
  var instanceMirror = calcInstance.type;
  for (var method in instanceMirror.declarations.values) {
    if (method is MethodMirror) {
      for (var annotation in method.metadata) {
        if (annotation.reflectee is Author) {
          var author = annotation.reflectee as Author;
          print('Method Author: ${author.name} (v${author.version})');
        }
      }
    }
  }

  // Reflection - invoke methods
  Calculator calc = Calculator();
  var addMethod = calcInstance.type.declarations[#add] as MethodMirror;
  var result = reflect(calc).invoke(#add, [5, 3]);
  print('Add(5,3) = ${result.reflectee}');

  // Get all methods
  print('
All methods:');
  for (var declaration in instanceMirror.declarations.values) {
    if (declaration is MethodMirror) {
      print('  ${declaration.simpleName}');
    }
  }

  // Dynamic invocation
  var multMethod = calcInstance.type.declarations[#multiply] as MethodMirror;
  var multResult = reflect(calc).invoke(#multiply, [4, 5]);
  print('Multiply(4,5) = ${multResult.reflectee}');
}
Advanced
58. What are Observer and Command Design Patterns in Dart?

Observer Pattern enables one-to-many notification. Command Pattern encapsulates requests as objects for queuing and undo.

  • Observer: Subject-observer relationship
  • Command: Action encapsulation with undo
  • Loose Coupling: Components remain independent
  • Undo/Redo: Command history support
dart
// Design Patterns - Observer and Command
// Observer Pattern
abstract class Observer {
  void update(String eventName, int data);
}

class Subject {
  List<Observer> _observers = [];
  int _data = 0;

  void subscribe(Observer o) {
    _observers.add(o);
  }

  void unsubscribe(Observer o) {
    _observers.remove(o);
  }

  int get data => _data;
  set data(int value) {
    _data = value;
    _notify();
  }

  void _notify() {
    for (var o in _observers) {
      o.update('Data Changed', _data);
    }
  }
}

class ConsoleObserver implements Observer {
  String name;

  ConsoleObserver(this.name);

  @override
  void update(String eventName, int data) {
    print('$name notified: $eventName = $data');
  }
}

// Command Pattern
abstract class Command {
  void execute();
  void undo();
}

class Counter {
  int _value = 0;

  void increment(int n) { _value += n; }
  void decrement(int n) { _value -= n; }
  int get value => _value;
}

class IncrementCommand implements Command {
  Counter counter;
  int amount;

  IncrementCommand(this.counter, this.amount);

  @override
  void execute() {
    counter.increment(amount);
  }

  @override
  void undo() {
    counter.decrement(amount);
  }
}

void main() {
  // Observer
  Subject subject = Subject();
  subject.subscribe(ConsoleObserver('Observer1'));
  subject.subscribe(ConsoleObserver('Observer2'));
  subject.data = 42;
  subject.data = 100;

  // Command
  Counter counter = Counter();
  List<Command> history = [];
  history.add(IncrementCommand(counter, 10));
  history.add(IncrementCommand(counter, 5));
  for (var cmd in history) cmd.execute();
  print('Counter: ${counter.value}');
  history.last.undo();
  print('After undo: ${counter.value}');
}
Advanced
59. What is Functional Programming in Dart?

Functional Programming uses pure functions, immutable data, and function composition for declarative code.

  • Higher-order Functions: Functions as parameters
  • Function Composition: Combine functions
  • Memoization: Cache function results
  • Immutability: Immutable data structures
dart
// Functional Programming in Dart
// Higher-order functions
List<T> mapList<T>(List<T> list, T Function(T) fn) {
  return list.map(fn).toList();
}

List<T> filterList<T>(List<T> list, bool Function(T) pred) {
  return list.where(pred).toList();
}

R reduceList<T, R>(List<T> list, R init, R Function(R, T) fn) {
  return list.fold(init, fn);
}

// Function composition
Function compose(Function f, Function g) {
  return (x) => f(g(x));
}

// Memoization
Function memoize(Function fn) {
  Map cache = {};
  return (x) {
    if (!cache.containsKey(x)) {
      cache[x] = fn(x);
    }
    return cache[x];
  };
}

void main() {
  List<int> nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

  var doubled = mapList(nums, (x) => x * 2);
  print('Doubled: ${doubled.join(' ')}');

  var evens = filterList(nums, (x) => x.isEven);
  print('Evens: ${evens.join(' ')}');

  int sum = reduceList(nums, 0, (acc, x) => acc + x);
  print('Sum: $sum');

  int addOne(int x) => x + 1;
  int doubleIt(int x) => x * 2;
  var addThenDouble = compose(doubleIt, addOne);
  print('Compose(double, +1)(5) = ${addThenDouble(5)}');

  // Memoized Fibonacci
  int fib(int n) => n <= 1 ? n : fib(n - 1) + fib(n - 2);
  var memoFib = memoize(fib);
  print('fib(30) = ${memoFib(30)}');
}
Advanced
60. What are Advanced Generics and Constraints in Dart?

Advanced Generics provide type safety with constraints, bounded types, and generic interfaces for flexible code.

  • Type Constraints: extends keyword
  • Generic Classes: Type parameter classes
  • Generic Methods: Type-safe methods
  • Repository Pattern: Generic data access
dart
// Advanced Generics and Constraints in Dart
// Generic class with constraints
class Repository<T> {
  List<T> _items = [];

  void add(T item) {
    _items.add(item);
  }

  T create() {
    // Dart doesn't support new T() directly
    // This is a workaround
    throw UnsupportedError('Cannot create instance of T');
  }

  List<T> getAll() => _items;
}

class Entity {
  int id;
  String name;

  Entity({this.id = 0, this.name = ''});
}

abstract class IRepository<T> {
  void add(T item);
  T? get(int id);
}

class GenericRepository<T> implements IRepository<T> {
  Map<int, T> _items = {};
  int _nextId = 1;

  @override
  void add(T item) {
    _items[_nextId++] = item;
  }

  @override
  T? get(int id) {
    return _items[id];
  }
}

void main() {
  Repository<Entity> repo = Repository<Entity>();
  Entity e1 = Entity(id: 1, name: 'Alice');
  repo.add(e1);
  Entity e2 = Entity(id: 2, name: 'Bob');
  repo.add(e2);

  for (var e in repo.getAll()) {
    print(e.name);
  }

  GenericRepository<Entity> genericRepo = GenericRepository<Entity>();
  genericRepo.add(Entity(id: 3, name: 'Carol'));
  Entity? found = genericRepo.get(3);
  print('Found: ${found?.name}');
}
Advanced
61. What are Matrix Operations in Dart?

Matrix Operations include multiplication, transposition, rotation, and other linear algebra operations.

  • Matrix Multiplication: Complex operation
  • Transposition: Flip rows/columns
  • Rotation: 90-degree rotation
  • Applications: Graphics, physics, ML
dart
// Matrix Operations in Dart
List<List<int>> multiply(List<List<int>> a, List<List<int>> b) {
  int r = a.length, c = b[0].length, k = b.length;
  List<List<int>> result = List.generate(r, (_) => List.filled(c, 0));
  for (int i = 0; i < r; i++) {
    for (int j = 0; j < c; j++) {
      for (int p = 0; p < k; p++) {
        result[i][j] += a[i][p] * b[p][j];
      }
    }
  }
  return result;
}

List<List<int>> transpose(List<List<int>> a) {
  int r = a.length, c = a[0].length;
  List<List<int>> result = List.generate(c, (_) => List.filled(r, 0));
  for (int i = 0; i < r; i++) {
    for (int j = 0; j < c; j++) {
      result[j][i] = a[i][j];
    }
  }
  return result;
}

void rotate90(List<List<int>> m) {
  int n = m.length;
  // Transpose
  for (int i = 0; i < n; i++) {
    for (int j = i + 1; j < n; j++) {
      int temp = m[i][j];
      m[i][j] = m[j][i];
      m[j][i] = temp;
    }
  }
  // Reverse each row
  for (int i = 0; i < n; i++) {
    m[i] = m[i].reversed.toList();
  }
}

void printMatrix(List<List<int>> m) {
  for (var row in m) {
    print(row.join(' '));
  }
}

void main() {
  List<List<int>> a = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
  ];

  List<List<int>> b = [
    [9, 8, 7],
    [6, 5, 4],
    [3, 2, 1]
  ];

  print('A*B:');
  printMatrix(multiply(a, b));
  print('T(A):');
  printMatrix(transpose(a));
  rotate90(a);
  print('A rotated 90CW:');
  printMatrix(a);
}
Advanced
62. What is Trapping Rain Water in Dart?

Trapping Rain Water calculates how much water can be trapped between bars using two-pointer technique.

  • Two-Pointer: Efficient O(n) solution
  • Left/Right Max: Track maximum heights
  • Water Volume: Sum of trapped water
  • Applications: Terrain analysis
dart
// Trapping Rain Water in Dart
int trap(List<int> height) {
  int l = 0, r = height.length - 1;
  int leftMax = 0, rightMax = 0, water = 0;
  while (l < r) {
    if (height[l] < height[r]) {
      if (height[l] >= leftMax) {
        leftMax = height[l];
      } else {
        water += leftMax - height[l];
      }
      l++;
    } else {
      if (height[r] >= rightMax) {
        rightMax = height[r];
      } else {
        water += rightMax - height[r];
      }
      r--;
    }
  }
  return water;
}

void main() {
  List<int> h1 = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1];
  print('Water trapped: ${trap(h1)}');

  List<int> h2 = [4, 2, 0, 3, 2, 5];
  print('Water trapped: ${trap(h2)}');
}
Advanced
63. What is Longest Increasing Subsequence (LIS) in Dart?

LIS finds the longest subsequence where elements are in increasing order using DP or binary search.

  • DP Solution: O(n²) time, O(n) space
  • Binary Search: O(n log n) time
  • Tail Tracking: Maintain increasing tails
  • Applications: Sequencing, bioinformatics
dart
// Longest Increasing Subsequence in Dart
// DP O(n^2)
int lisDP(List<int> arr) {
  int n = arr.length;
  List<int> dp = List.filled(n, 1);
  for (int i = 1; i < n; i++) {
    for (int j = 0; j < i; j++) {
      if (arr[j] < arr[i] && dp[j] + 1 > dp[i]) {
        dp[i] = dp[j] + 1;
      }
    }
  }
  return dp.reduce((a, b) => a > b ? a : b);
}

// Binary Search O(n log n)
int lisBS(List<int> arr) {
  List<int> tails = [];
  for (int x in arr) {
    int idx = tails.lastIndexWhere((v) => v >= x) + 1;
    if (idx == tails.length) {
      tails.add(x);
    } else {
      tails[idx] = x;
    }
  }
  return tails.length;
}

void main() {
  List<int> arr = [10, 9, 2, 5, 3, 7, 101, 18];
  print('LIS (DP): ${lisDP(arr)}');
  print('LIS (BS): ${lisBS(arr)}');
}
Advanced
64. How does Bellman-Ford Algorithm work in Dart?

Bellman-Ford finds shortest paths in weighted graphs, handling negative edges and detecting negative cycles.

  • Negative Edges: Handles negative weights
  • Edge Relaxation: V-1 iterations
  • Cycle Detection: Identify negative cycles
  • Applications: Routing, network protocols
dart
// Bellman-Ford in Dart
class Edge {
  int u, v, w;
  Edge(this.u, this.v, this.w);
}

void bellmanFord(List<Edge> edges, int v, int src) {
  List<int> dist = List.filled(v, 9223372036854775807);
  dist[src] = 0;

  for (int i = 1; i < v; i++) {
    for (var e in edges) {
      if (dist[e.u] != 9223372036854775807 &&
          dist[e.u] + e.w < dist[e.v]) {
        dist[e.v] = dist[e.u] + e.w;
      }
    }
  }

  // Check negative cycle
  for (var e in edges) {
    if (dist[e.u] != 9223372036854775807 &&
        dist[e.u] + e.w < dist[e.v]) {
      print('Negative cycle detected!');
      return;
    }
  }

  print('Distances from $src:');
  for (int i = 0; i < v; i++) {
    print('  $i: ${dist[i] == 9223372036854775807 ? -1 : dist[i]}');
  }
}

void main() {
  int v = 5;
  List<Edge> edges = [
    Edge(0, 1, -1),
    Edge(0, 2, 4),
    Edge(1, 2, 3),
    Edge(1, 3, 2),
    Edge(1, 4, 2),
    Edge(3, 2, 5),
    Edge(3, 1, 1),
    Edge(4, 3, -3)
  ];
  bellmanFord(edges, v, 0);
}
Advanced
65. What is Floyd-Warshall Algorithm in Dart?

Floyd-Warshall finds all-pairs shortest paths in a weighted graph using dynamic programming in O(V³) time.

  • All-Pairs Shortest Path: Between all vertices
  • DP Approach: Intermediate vertex iteration
  • Negative Edges: Handles without negative cycles
  • Applications: Routing, transitive closure
dart
// Floyd-Warshall in Dart
void floydWarshall(List<List<int>> dist) {
  int v = dist.length;
  for (int k = 0; k < v; k++) {
    for (int i = 0; i < v; i++) {
      for (int j = 0; j < v; j++) {
        if (dist[i][k] != 9223372036854775807 &&
            dist[k][j] != 9223372036854775807) {
          int newDist = dist[i][k] + dist[k][j];
          if (newDist < dist[i][j]) {
            dist[i][j] = newDist;
          }
        }
      }
    }
  }

  print('All-Pairs Shortest Paths:');
  for (int i = 0; i < v; i++) {
    for (int j = 0; j < v; j++) {
      print(dist[i][j] == 9223372036854775807 ? 'INF ' : '${dist[i][j]} ');
    }
    print('');
  }
}

void main() {
  const int INF = 9223372036854775807;
  List<List<int>> graph = [
    [0, 3, INF, 7],
    [8, 0, 2, INF],
    [5, INF, 0, 1],
    [2, INF, INF, 0]
  ];
  floydWarshall(graph);
}
Advanced
66. How does Kruskal's MST Algorithm work in Dart?

Kruskal's Algorithm finds a Minimum Spanning Tree by sorting edges and using union-find to add them without cycles.

  • Edge Sorting: Sort by weight
  • Union-Find: Cycle detection
  • MST Construction: Build spanning tree
  • Applications: Network design, clustering
dart
// Kruskal's MST in Dart
class EdgeK {
  int u, v, w;
  EdgeK(this.u, this.v, this.w);
}

class DSU {
  List<int> parent, rank;

  DSU(int n)
      : parent = List.generate(n, (i) => i),
        rank = List.filled(n, 0);

  int find(int x) {
    if (parent[x] != x) {
      parent[x] = find(parent[x]);
    }
    return parent[x];
  }

  bool unite(int x, int y) {
    int px = find(x);
    int py = find(y);
    if (px == py) return false;
    if (rank[px] < rank[py]) {
      int temp = px;
      px = py;
      py = temp;
    }
    parent[py] = px;
    if (rank[px] == rank[py]) rank[px]++;
    return true;
  }
}

void main() {
  int v = 4;
  List<EdgeK> edges = [
    EdgeK(0, 1, 10),
    EdgeK(0, 2, 6),
    EdgeK(0, 3, 5),
    EdgeK(1, 3, 15),
    EdgeK(2, 3, 4)
  ];
  edges.sort((a, b) => a.w.compareTo(b.w));

  DSU dsu = DSU(v);
  int cost = 0;
  print('MST Edges:');
  for (var e in edges) {
    if (dsu.unite(e.u, e.v)) {
      print('${e.u} -- ${e.v} (weight ${e.w})');
      cost += e.w;
    }
  }
  print('MST Cost: $cost');
}
Advanced
67. What are String Algorithms in Dart?

String Algorithms include longest palindrome, anagram checking, and grouping anagrams for text processing.

  • Longest Palindrome: Expand around center
  • Anagram Check: Frequency counting
  • Group Anagrams: Sort strings as keys
  • Applications: Text analysis, NLP
dart
// String Algorithms in Dart
// Longest palindromic substring
String longestPalindrome(String s) {
  int n = s.length, start = 0, maxLen = 1;
  void expand(int l, int r) {
    while (l >= 0 && r < n && s[l] == s[r]) {
      l--;
      r++;
    }
    if (r - l - 1 > maxLen) {
      maxLen = r - l - 1;
      start = l + 1;
    }
  }

  for (int i = 0; i < n; i++) {
    expand(i, i);
    expand(i, i + 1);
  }
  return s.substring(start, start + maxLen);
}

// Check anagram
bool isAnagram(String s1, String s2) {
  if (s1.length != s2.length) return false;
  Map<String, int> freq = {};
  for (String c in s1.split('')) {
    freq[c] = (freq[c] ?? 0) + 1;
  }
  for (String c in s2.split('')) {
    if (!freq.containsKey(c)) return false;
    freq[c] = freq[c]! - 1;
    if (freq[c]! < 0) return false;
  }
  return true;
}

// Group anagrams
List<List<String>> groupAnagrams(List<String> words) {
  Map<String, List<String>> map = {};
  for (String w in words) {
    String key = w.split('')..sort()..join();
    map.putIfAbsent(key, () => []).add(w);
  }
  return map.values.toList();
}

void main() {
  print(longestPalindrome('babad'));
  print(isAnagram('listen', 'silent'));

  List<String> words = ['eat', 'tea', 'tan', 'ate', 'nat', 'bat'];
  for (var group in groupAnagrams(words)) {
    print(group.join(' '));
  }
}
Advanced
68. What are Coin Change and Subset Sum in Dart?

Coin Change and Subset Sum are classic DP problems dealing with combinations and sums of values.

  • Minimum Coins: Minimum coins for amount
  • Count Ways: Number of combinations
  • Subset Sum: Check if sum is possible
  • Applications: Financial, resource allocation
dart
// Coin Change and Subset Sum in Dart
// Minimum coins
int coinChange(List<int> coins, int amount) {
  List<int> dp = List.filled(amount + 1, 9223372036854775807);
  dp[0] = 0;
  for (int i = 1; i <= amount; i++) {
    for (int c in coins) {
      if (c <= i && dp[i - c] != 9223372036854775807) {
        dp[i] = dp[i] < dp[i - c] + 1 ? dp[i] : dp[i - c] + 1;
      }
    }
  }
  return dp[amount] == 9223372036854775807 ? -1 : dp[amount];
}

// Count ways
int countWays(List<int> coins, int amount) {
  List<int> dp = List.filled(amount + 1, 0);
  dp[0] = 1;
  for (int c in coins) {
    for (int i = c; i <= amount; i++) {
      dp[i] += dp[i - c];
    }
  }
  return dp[amount];
}

// Subset sum
bool subsetSum(List<int> arr, int target) {
  int n = arr.length;
  List<List<bool>> dp = List.generate(n + 1, (_) => List.filled(target + 1, false));
  for (int i = 0; i <= n; i++) dp[i][0] = true;
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= target; j++) {
      dp[i][j] = dp[i - 1][j];
      if (arr[i - 1] <= j) {
        dp[i][j] = dp[i][j] || dp[i - 1][j - arr[i - 1]];
      }
    }
  }
  return dp[n][target];
}

void main() {
  List<int> coins = [1, 5, 6, 9];
  print('Min coins for 11: ${coinChange(coins, 11)}');
  print('Ways for 10: ${countWays(coins, 10)}');

  List<int> arr = [3, 34, 4, 12, 5, 2];
  print('Subset sum 9: ${subsetSum(arr, 9)}');
  print('Subset sum 30: ${subsetSum(arr, 30)}');
}
Advanced
69. What are Monotonic Stack Problems in Dart?

Monotonic Stack maintains elements in sorted order for problems like next greater element and largest rectangle in histogram.

  • Next Greater Element: Find next greater in array
  • Largest Rectangle: Max area in histogram
  • Stack Maintenance: Keep monotonic property
  • Applications: Data analysis, pattern finding
dart
// Monotonic Stack Problems
// Next Greater Element
List<int> nextGreater(List<int> arr) {
  int n = arr.length;
  List<int> result = List.filled(n, -1);
  List<int> stack = [];
  for (int i = 0; i < n; i++) {
    while (stack.isNotEmpty && arr[stack.last] < arr[i]) {
      result[stack.removeLast()] = arr[i];
    }
    stack.add(i);
  }
  return result;
}

// Largest Rectangle in Histogram
int largestRect(List<int> heights) {
  List<int> stack = [];
  int maxArea = 0;
  List<int> h = [...heights, 0];
  for (int i = 0; i < h.length; i++) {
    while (stack.isNotEmpty && h[stack.last] > h[i]) {
      int height = h[stack.removeLast()];
      int width = stack.isEmpty ? i : i - stack.last - 1;
      int area = height * width;
      if (area > maxArea) maxArea = area;
    }
    stack.add(i);
  }
  return maxArea;
}

void main() {
  List<int> arr = [4, 5, 2, 10, 8];
  List<int> ng = nextGreater(arr);
  print('Next Greater: ${ng.join(' ')}');

  List<int> h = [2, 1, 5, 6, 2, 3];
  print('Largest Rect: ${largestRect(h)}');
}
Advanced
70. What are Binary Search Variants in Dart?

Binary Search Variants handle rotated arrays, peak finding, and finding first/last occurrences of elements.

  • Rotated Array Search: Binary search in rotated sorted
  • Peak Finding: Find any peak element
  • First/Last Position: Range queries
  • Applications: Data structures, algorithms
dart
// Binary Search Variants in Dart
// Search in rotated sorted array
int searchRotated(List<int> arr, int target) {
  int l = 0, r = arr.length - 1;
  while (l <= r) {
    int mid = (l + r) ~/ 2;
    if (arr[mid] == target) return mid;
    if (arr[l] <= arr[mid]) {
      if (target >= arr[l] && target < arr[mid]) {
        r = mid - 1;
      } else {
        l = mid + 1;
      }
    } else {
      if (target > arr[mid] && target <= arr[r]) {
        l = mid + 1;
      } else {
        r = mid - 1;
      }
    }
  }
  return -1;
}

// Find peak element
int findPeak(List<int> arr) {
  int l = 0, r = arr.length - 1;
  while (l < r) {
    int mid = (l + r) ~/ 2;
    if (arr[mid] > arr[mid + 1]) {
      r = mid;
    } else {
      l = mid + 1;
    }
  }
  return l;
}

// First and last position
(int, int) firstLast(List<int> arr, int target) {
  int first = arr.indexOf(target);
  if (first == -1) return (-1, -1);
  int last = arr.lastIndexOf(target);
  return (first, last);
}

void main() {
  List<int> rotated = [4, 5, 6, 7, 0, 1, 2];
  print('Search 0: ${searchRotated(rotated, 0)}');

  List<int> arr = [1, 2, 3, 1];
  print('Peak index: ${findPeak(arr)}');

  List<int> v = [5, 7, 7, 8, 8, 10];
  var (f, l) = firstLast(v, 8);
  print('First,Last of 8: $f,$l');
}
Advanced
71. What is Product of Array Except Self in Dart?

Product of Array Except Self calculates the product of all elements except the current one in O(n) time.

  • Left and Right Passes: Track products
  • In-Place Solution: No extra space
  • O(n) Time: Single pass each direction
  • Applications: Array calculations
dart
// Product of Array Except Self in Dart
List<int> productExceptSelf(List<int> nums) {
  int n = nums.length;
  List<int> result = List.filled(n, 1);

  // Left pass
  for (int i = 1; i < n; i++) {
    result[i] = result[i - 1] * nums[i - 1];
  }

  // Right pass
  int right = 1;
  for (int i = n - 1; i >= 0; i--) {
    result[i] *= right;
    right *= nums[i];
  }
  return result;
}

void main() {
  List<int> nums = [1, 2, 3, 4];
  List<int> res = productExceptSelf(nums);
  print('Output: ${res.join(' ')}');
}
Advanced
72. What are Flood Fill and Number of Islands in Dart?

Flood Fill and Number of Islands are graph traversal problems using DFS/BFS for connected component detection.

  • Flood Fill: Color replacement algorithm
  • Number of Islands: Count connected land cells
  • DFS Traversal: Depth-first on grid
  • Applications: Image processing, maps
dart
// Flood Fill and Number of Islands
// Flood Fill
void floodFill(List<List<int>> img, int r, int c, int oldColor, int newColor) {
  if (r < 0 || r >= img.length || c < 0 || c >= img[0].length) return;
  if (img[r][c] != oldColor || img[r][c] == newColor) return;
  img[r][c] = newColor;
  floodFill(img, r + 1, c, oldColor, newColor);
  floodFill(img, r - 1, c, oldColor, newColor);
  floodFill(img, r, c + 1, oldColor, newColor);
  floodFill(img, r, c - 1, oldColor, newColor);
}

// Number of Islands
void dfs(List<List<String>> grid, int r, int c) {
  if (r < 0 || r >= grid.length || c < 0 || c >= grid[0].length) return;
  if (grid[r][c] == '0') return;
  grid[r][c] = '0';
  dfs(grid, r + 1, c);
  dfs(grid, r - 1, c);
  dfs(grid, r, c + 1);
  dfs(grid, r, c - 1);
}

int numIslands(List<List<String>> grid) {
  int count = 0;
  for (int r = 0; r < grid.length; r++) {
    for (int c = 0; c < grid[0].length; c++) {
      if (grid[r][c] == '1') {
        dfs(grid, r, c);
        count++;
      }
    }
  }
  return count;
}

void main() {
  List<List<String>> grid = [
    ['1', '1', '0', '0'],
    ['1', '1', '0', '0'],
    ['0', '0', '1', '0'],
    ['0', '0', '0', '1']
  ];
  print('Islands: ${numIslands(grid)}');
}
Advanced
73. How does Word Search work in Dart?

Word Search finds words in a 2D grid using DFS with backtracking, checking all directions from each cell.

  • DFS Traversal: Explore adjacent cells
  • Backtracking: Mark visited cells
  • Efficient Search: Early termination
  • Applications: Word games, puzzles
dart
// Word Search in Grid
bool dfs(List<List<String>> board, String word, int r, int c, int idx) {
  if (idx == word.length) return true;
  if (r < 0 || r >= board.length || c < 0 || c >= board[0].length) return false;
  if (board[r][c] != word[idx]) return false;

  String tmp = board[r][c];
  board[r][c] = '#';
  bool found = dfs(board, word, r + 1, c, idx + 1) ||
               dfs(board, word, r - 1, c, idx + 1) ||
               dfs(board, word, r, c + 1, idx + 1) ||
               dfs(board, word, r, c - 1, idx + 1);
  board[r][c] = tmp;
  return found;
}

bool wordSearch(List<List<String>> board, String word) {
  for (int r = 0; r < board.length; r++) {
    for (int c = 0; c < board[0].length; c++) {
      if (dfs(board, word, r, c, 0)) return true;
    }
  }
  return false;
}

void main() {
  List<List<String>> board = [
    ['A', 'B', 'C', 'E'],
    ['S', 'F', 'C', 'S'],
    ['A', 'D', 'E', 'E']
  ];
  print(wordSearch(board, 'ABCCED'));
  print(wordSearch(board, 'SEE'));
  print(wordSearch(board, 'ABCB'));
}
Advanced
74. What is Spiral Matrix in Dart?

Spiral Matrix traverses a 2D matrix in spiral order, using four boundaries that shrink as we progress.

  • Boundary Tracking: Top, bottom, left, right
  • Direction Changes: Moving clockwise
  • Layer-by-Layer: Process outer to inner
  • Applications: Matrix manipulation
dart
// Spiral Matrix in Dart
List<int> spiralOrder(List<List<int>> matrix) {
  List<int> result = [];
  int top = 0, bottom = matrix.length - 1;
  int left = 0, right = matrix[0].length - 1;

  while (top <= bottom && left <= right) {
    for (int i = left; i <= right; i++) result.add(matrix[top][i]);
    top++;
    for (int i = top; i <= bottom; i++) result.add(matrix[i][right]);
    right--;
    if (top <= bottom) {
      for (int i = right; i >= left; i--) result.add(matrix[bottom][i]);
      bottom--;
    }
    if (left <= right) {
      for (int i = bottom; i >= top; i--) result.add(matrix[i][left]);
      left++;
    }
  }
  return result;
}

void main() {
  List<List<int>> mat = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12],
    [13, 14, 15, 16]
  ];
  print('Spiral: ${spiralOrder(mat).join(' ')}');
}
Advanced
75. How does Sudoku Solver work in Dart?

Sudoku Solver uses backtracking to fill empty cells with valid numbers, checking row, column, and box constraints.

  • Constraint Checking: Row, column, box
  • Backtracking: Try numbers recursively
  • Efficient Search: Early validation
  • Applications: Puzzle solving, CSP
dart
// Sudoku Solver in Dart
bool isValid(List<List<String>> board, int r, int c, String num) {
  for (int i = 0; i < 9; i++) {
    if (board[r][i] == num) return false;
    if (board[i][c] == num) return false;
    int boxR = 3 * (r ~/ 3) + i ~/ 3;
    int boxC = 3 * (c ~/ 3) + i % 3;
    if (board[boxR][boxC] == num) return false;
  }
  return true;
}

bool solve(List<List<String>> board) {
  for (int r = 0; r < 9; r++) {
    for (int c = 0; c < 9; c++) {
      if (board[r][c] == '.') {
        for (String num in '123456789'.split('')) {
          if (isValid(board, r, c, num)) {
            board[r][c] = num;
            if (solve(board)) return true;
            board[r][c] = '.';
          }
        }
        return false;
      }
    }
  }
  return true;
}

void main() {
  List<List<String>> board = [
    ['5','3','.','.','7','.','.','.','.'],
    ['6','.','.','1','9','5','.','.','.'],
    ['.','9','8','.','.','.','.','6','.'],
    ['8','.','.','.','6','.','.','.','3'],
    ['4','.','.','8','.','3','.','.','1'],
    ['7','.','.','.','2','.','.','.','6'],
    ['.','6','.','.','.','.','2','8','.'],
    ['.','.','.','4','1','9','.','.','5'],
    ['.','.','.','.','8','.','.','7','9']
  ];
  solve(board);
  for (var row in board) {
    print(row.join(' '));
  }
}
Advanced
76. What is Priority Queue Custom Comparator in Dart?

Priority Queue with Custom Comparator allows ordering elements based on custom criteria using Comparator interface.

  • Custom Comparator: Define ordering logic
  • Task Scheduling: Priority-based execution
  • Multiple Criteria: Compare by multiple fields
  • Applications: Scheduling, event handling
dart
// Priority Queue Custom Comparator
import 'dart:collection';

class Task {
  String name;
  int priority;
  int deadline;

  Task(this.name, this.priority, this.deadline);
}

class TaskComparer implements Comparator<Task> {
  @override
  int compare(Task a, Task b) {
    if (a.priority != b.priority) {
      return b.priority.compareTo(a.priority);
    }
    return a.deadline.compareTo(b.deadline);
  }
}

void main() {
  PriorityQueue<Task> taskQueue = PriorityQueue<Task>(TaskComparer());
  taskQueue.add(Task('Write Report', 3, 5));
  taskQueue.add(Task('Fix Bug', 5, 2));
  taskQueue.add(Task('Code Review', 4, 3));
  taskQueue.add(Task('Deploy Feature', 5, 1));
  taskQueue.add(Task('Write Tests', 3, 4));

  print('Task execution order:');
  while (taskQueue.isNotEmpty) {
    Task t = taskQueue.removeFirst();
    print('  [P=${t.priority},D=${t.deadline}] ${t.name}');
  }
}
Advanced
77. What is Prim's MST Algorithm in Dart?

Prim's Algorithm finds a Minimum Spanning Tree by growing the tree one edge at a time using a priority queue.

  • Greedy Approach: Add minimum edge
  • Priority Queue: Efficient edge selection
  • Tree Growth: Expand from start vertex
  • Applications: Network design, clustering
dart
// Graph - Prim's MST in Dart
int primMST(List<List<(int, int)>> graph, int v) {
  List<int> key = List.filled(v, 9223372036854775807);
  List<bool> inMST = List.filled(v, false);
  PriorityQueue<(int, int)> pq = PriorityQueue<(int, int)>(
    (a, b) => a.$1.compareTo(b.$1)
  );

  key[0] = 0;
  pq.add((0, 0));
  int totalCost = 0;

  while (pq.isNotEmpty) {
    var (weight, u) = pq.removeFirst();
    if (inMST[u]) continue;
    inMST[u] = true;
    totalCost += weight;

    for (var (w, v) in graph[u]) {
      if (!inMST[v] && w < key[v]) {
        key[v] = w;
        pq.add((w, v));
      }
    }
  }
  return totalCost;
}

void main() {
  int v = 5;
  List<List<(int, int)>> graph = List.generate(v, (_) => []);

  void addEdge(int u, int v, int w) {
    graph[u].add((w, v));
    graph[v].add((w, u));
  }

  addEdge(0, 1, 2);
  addEdge(0, 3, 6);
  addEdge(1, 2, 3);
  addEdge(1, 3, 8);
  addEdge(1, 4, 5);
  addEdge(2, 4, 7);
  addEdge(3, 4, 9);

  print('MST Cost (Prim's): ${primMST(graph, v)}');
}
Advanced
78. How does Custom Iterator Pattern work in Dart?

Custom Iterator Pattern enables creating custom iterable objects with specific iteration logic like ranges or sequences.

  • Iterator Interface: moveNext(), current
  • Iterable: Create custom sequences
  • Lazy Evaluation: Generate on demand
  • Applications: Custom collections, sequences
dart
// Custom Iterator Pattern in Dart
// Custom Range iterator
class Range extends Iterable<int> {
  final int start, end, step;

  Range(this.start, this.end, [this.step = 1]);

  @override
  Iterator<int> get iterator => _RangeIterator(start, end, step);
}

class _RangeIterator implements Iterator<int> {
  int _current;
  final int end, step;

  _RangeIterator(this._current, this.end, this.step);

  @override
  int get current => _current;

  @override
  bool moveNext() {
    if (_current < end) {
      _current += step;
      return true;
    }
    return false;
  }
}

// Custom Fibonacci generator
class Fibonacci extends Iterable<int> {
  final int count;

  Fibonacci(this.count);

  @override
  Iterator<int> get iterator => _FibonacciIterator(count);
}

class _FibonacciIterator implements Iterator<int> {
  int _count, _index = 0;
  int _current = 0;
  int _a = 0, _b = 1;

  _FibonacciIterator(this._count);

  @override
  int get current => _current;

  @override
  bool moveNext() {
    if (_index >= _count) return false;
    _current = _a;
    int c = _a + _b;
    _a = _b;
    _b = c;
    _index++;
    return true;
  }
}

void main() {
  // Custom range
  for (int x in Range(1, 11)) {
    print('$x ');
  }
  print('');

  for (int x in Range(0, 20, 2)) {
    print('$x ');
  }
  print('');

  // Custom fibonacci
  for (int x in Fibonacci(10)) {
    print('$x ');
  }
  print('');

  // LINQ with custom iterator
  var evens = Range(1, 21).where((x) => x.isEven);
  print('Evens: ${evens.join(' ')}');
}
Advanced
79. How do you implement Stack and Queue in Dart?

Stack (LIFO) and Queue (FIFO) are fundamental data structures with custom implementations for specific needs.

  • Stack Implementation: List-based push/pop
  • Queue Implementation: ListQueue for efficiency
  • Operations: Push, pop, enqueue, dequeue
  • Applications: Various algorithms
dart
// Stack and Queue Implementations
// Custom Stack
class MyStack<T> {
  List<T> _items = [];

  void push(T item) {
    _items.add(item);
  }

  T pop() {
    if (_items.isEmpty) throw StateError('Stack is empty');
    return _items.removeLast();
  }

  T peek() {
    if (_items.isEmpty) throw StateError('Stack is empty');
    return _items.last;
  }

  bool get isEmpty => _items.isEmpty;
  int get length => _items.length;
}

// Custom Queue
class MyQueue<T> {
  ListQueue<T> _items = ListQueue<T>();

  void enqueue(T item) {
    _items.add(item);
  }

  T dequeue() {
    if (_items.isEmpty) throw StateError('Queue is empty');
    return _items.removeFirst();
  }

  T peek() {
    if (_items.isEmpty) throw StateError('Queue is empty');
    return _items.first;
  }

  bool get isEmpty => _items.isEmpty;
  int get length => _items.length;
}

void main() {
  // Custom Stack
  MyStack<int> stack = MyStack<int>();
  stack.push(10);
  stack.push(20);
  stack.push(30);
  print('Stack top: ${stack.peek()}');
  while (!stack.isEmpty) {
    print('${stack.pop()} ');
  }
  print('');

  // Custom Queue
  MyQueue<int> queue = MyQueue<int>();
  queue.enqueue(10);
  queue.enqueue(20);
  queue.enqueue(30);
  print('Queue front: ${queue.peek()}');
  while (!queue.isEmpty) {
    print('${queue.dequeue()} ');
  }
  print('');
}
Advanced
80. What are Counting Sort and Radix Sort in Dart?

Counting Sort and Radix Sort are non-comparison sorting algorithms efficient for specific input types.

  • Counting Sort: O(n+k) for integers
  • Radix Sort: Digit-by-digit sorting
  • Linear Time: Efficient for certain data
  • Applications: Integer sorting, strings
dart
// Counting Sort and Radix Sort in Dart
void countingSort(List<int> arr) {
  if (arr.isEmpty) return;
  int maxVal = arr.reduce((a, b) => a > b ? a : b);
  List<int> count = List.filled(maxVal + 1, 0);
  for (int x in arr) count[x]++;

  int idx = 0;
  for (int i = 0; i <= maxVal; i++) {
    while (count[i]-- > 0) {
      arr[idx++] = i;
    }
  }
}

void countSortByDigit(List<int> arr, int exp) {
  int n = arr.length;
  List<int> output = List.filled(n, 0);
  List<int> count = List.filled(10, 0);

  for (int x in arr) {
    count[(x ~/ exp) % 10]++;
  }

  for (int i = 1; i < 10; i++) {
    count[i] += count[i - 1];
  }

  for (int i = n - 1; i >= 0; i--) {
    int digit = (arr[i] ~/ exp) % 10;
    output[count[digit] - 1] = arr[i];
    count[digit]--;
  }

  for (int i = 0; i < n; i++) {
    arr[i] = output[i];
  }
}

void radixSort(List<int> arr) {
  if (arr.isEmpty) return;
  int maxVal = arr.reduce((a, b) => a > b ? a : b);
  for (int exp = 1; maxVal ~/ exp > 0; exp *= 10) {
    countSortByDigit(arr, exp);
  }
}

void main() {
  List<int> v1 = [4, 2, 2, 8, 3, 3, 1, 7, 5];
  countingSort(v1);
  print('Counting: ${v1.join(' ')}');

  List<int> v2 = [170, 45, 75, 90, 802, 24, 2, 66];
  radixSort(v2);
  print('Radix: ${v2.join(' ')}');
}
Advanced
81. How does Graph Cycle Detection work in Dart?

Cycle Detection identifies cycles in directed and undirected graphs using DFS recursion stack or union-find.

  • Directed Graph: DFS with recursion stack
  • Undirected Graph: Union-Find approach
  • Back Edges: Indicate cycles
  • Applications: Deadlock detection, validation
dart
// Graph Cycle Detection in Dart
// Directed graph - DFS with recursion stack
bool dfsCycle(int v, List<List<int>> adj, List<bool> visited, List<bool> recStack) {
  visited[v] = true;
  recStack[v] = true;

  for (int u in adj[v]) {
    if (!visited[u] && dfsCycle(u, adj, visited, recStack)) {
      return true;
    } else if (recStack[u]) {
      return true;
    }
  }
  recStack[v] = false;
  return false;
}

bool hasCycleDirected(int v, List<List<int>> adj) {
  List<bool> visited = List.filled(v, false);
  List<bool> recStack = List.filled(v, false);
  for (int i = 0; i < v; i++) {
    if (!visited[i] && dfsCycle(i, adj, visited, recStack)) {
      return true;
    }
  }
  return false;
}

// Undirected graph - Union Find
bool hasCycleUndirected(int v, List<(int, int)> edges) {
  List<int> parent = List.generate(v, (i) => i);

  int find(int x) {
    if (parent[x] != x) {
      parent[x] = find(parent[x]);
    }
    return parent[x];
  }

  for (var (u, v) in edges) {
    int pu = find(u);
    int pv = find(v);
    if (pu == pv) return true;
    parent[pu] = pv;
  }
  return false;
}

void main() {
  int v = 4;
  List<List<int>> adj = List.generate(v, (_) => []);
  adj[0].add(1);
  adj[1].add(2);
  adj[2].add(3);
  adj[3].add(1);

  print('Directed cycle: ${hasCycleDirected(v, adj)}');

  List<(int, int)> edges = [(0, 1), (1, 2), (2, 0)];
  print('Undirected cycle: ${hasCycleUndirected(3, edges)}');
}
Advanced
82. What is Advanced Functional Programming in Dart?

Advanced Functional Programming includes group joins, select many, and complex aggregations with collections.

  • Group Join: Left outer join operations
  • Select Many: Flatten collections
  • Group By: Group elements by key
  • Aggregations: Complex data transformations
dart
// Advanced Functional Programming
class Customer {
  int id;
  String name;

  Customer(this.id, this.name);
}

class Order {
  int customerId;
  String product;
  int quantity;

  Order(this.customerId, this.product, this.quantity);
}

void main() {
  List<Customer> customers = [
    Customer(1, 'Alice'),
    Customer(2, 'Bob'),
    Customer(3, 'Carol')
  ];

  List<Order> orders = [
    Order(1, 'Laptop', 1),
    Order(1, 'Mouse', 2),
    Order(2, 'Keyboard', 1),
    Order(2, 'Monitor', 3),
    Order(2, 'Mouse', 1)
  ];

  // GroupJoin (left outer join)
  var customerOrders = customers.map((c) {
    return (
      name: c.name,
      orders: orders.where((o) => o.customerId == c.id)
          .map((o) => '${o.product} (x${o.quantity})')
          .toList()
    );
  }).toList();

  print('Customer Orders:');
  for (var co in customerOrders) {
    print('${co.name}: ${co.orders.join(', ')}');
  }

  // SelectMany (flatten)
  var allOrderItems = orders.expand((o) => List.filled(o.quantity, o.product)).toList();
  print('All items: ${allOrderItems.join(', ')}');

  // Group by
  var orderLookup = orders.fold<Map<int, List<Order>>>({}, (map, o) {
    map.putIfAbsent(o.customerId, () => []).add(o);
    return map;
  });
  orderLookup.forEach((id, orders) {
    print('Customer $id has ${orders.length} orders');
  });

  // Aggregate
  String allProducts = orders.map((o) => o.product).join(', ');
  print('All products: $allProducts');
}
Advanced
83. How does Expression Evaluation work using Stack in Dart?

Expression Evaluation uses stacks to evaluate RPN expressions and convert infix to postfix notation.

  • RPN Evaluation: Postfix expression evaluation
  • Infix to Postfix: Shunting-yard algorithm
  • Operator Precedence: Handling precedence rules
  • Applications: Calculators, compilers
dart
// Expression Evaluation using Stack
// Evaluate Reverse Polish Notation
int evalRPN(List<String> tokens) {
  List<int> stack = [];
  for (String t in tokens) {
    switch (t) {
      case '+':
        int b = stack.removeLast();
        int a = stack.removeLast();
        stack.add(a + b);
        break;
      case '-':
        int b = stack.removeLast();
        int a = stack.removeLast();
        stack.add(a - b);
        break;
      case '*':
        int b = stack.removeLast();
        int a = stack.removeLast();
        stack.add(a * b);
        break;
      case '/':
        int b = stack.removeLast();
        int a = stack.removeLast();
        stack.add(a ~/ b);
        break;
      default:
        stack.add(int.parse(t));
    }
  }
  return stack.removeLast();
}

// Infix to Postfix
String infixToPostfix(String expr) {
  List<String> ops = [];
  List<String> result = [];

  int precedence(String c) {
    switch (c) {
      case '+':
      case '-':
        return 1;
      case '*':
      case '/':
        return 2;
      default:
        return 0;
    }
  }

  for (String c in expr.split('')) {
    if (c.contains(RegExp(r'[0-9]'))) {
      result.add(c);
    } else if (c == '(') {
      ops.add(c);
    } else if (c == ')') {
      while (ops.last != '(') {
        result.add(ops.removeLast());
      }
      ops.removeLast();
    } else {
      while (ops.isNotEmpty && precedence(ops.last) >= precedence(c)) {
        result.add(ops.removeLast());
      }
      ops.add(c);
    }
  }

  while (ops.isNotEmpty) {
    result.add(ops.removeLast());
  }

  return result.join(' ');
}

void main() {
  List<String> rpn = ['2', '1', '+', '3', '*'];
  print('RPN eval: ${evalRPN(rpn)}');

  print('Infix to Postfix: ${infixToPostfix('(2+3)*4')}');
}
Advanced
84. What are Strategy and Template Design Patterns in Dart?

Strategy Pattern enables interchangeable algorithms. Template Method defines an algorithm skeleton with customizable steps.

  • Strategy: Family of algorithms
  • Template Method: Algorithm structure
  • Flexibility: Dynamic algorithm selection
  • Applications: Framework design, algorithms
dart
// Design Patterns - Strategy and Template
// Strategy Pattern
abstract class SortStrategy {
  void sort(List<int> data);
  String get name;
}

class BubbleSortStrategy implements SortStrategy {
  @override
  String get name => 'Bubble Sort';

  @override
  void sort(List<int> data) {
    int n = data.length;
    for (int i = 0; i < n - 1; i++) {
      bool swapped = false;
      for (int j = 0; j < n - i - 1; j++) {
        if (data[j] > data[j + 1]) {
          int temp = data[j];
          data[j] = data[j + 1];
          data[j + 1] = temp;
          swapped = true;
        }
      }
      if (!swapped) break;
    }
  }
}

class BuiltInSortStrategy implements SortStrategy {
  @override
  String get name => 'Built-in Sort';

  @override
  void sort(List<int> data) {
    data.sort();
  }
}

class SortContext {
  SortStrategy _strategy;

  SortContext(this._strategy);

  void setStrategy(SortStrategy strategy) {
    _strategy = strategy;
  }

  void sort(List<int> data) {
    print('Using: ${_strategy.name}');
    _strategy.sort(data);
  }
}

// Template Method Pattern
abstract class DataProcessor {
  void process() {
    loadData();
    processData();
    saveResult();
  }

  void loadData();
  void processData();
  void saveResult();
}

class CSVProcessor extends DataProcessor {
  @override
  void loadData() {
    print('Loading CSV data...');
  }

  @override
  void processData() {
    print('Processing CSV data...');
  }

  @override
  void saveResult() {
    print('Saving CSV result...');
  }
}

void main() {
  List<int> data = [5, 3, 8, 1, 9, 2];

  SortContext context = SortContext(BubbleSortStrategy());
  context.sort(List.from(data));
  print(data.join(' '));

  context.setStrategy(BuiltInSortStrategy());
  context.sort(List.from(data));
  print(data.join(' '));

  print('
Template Method:');
  DataProcessor processor = CSVProcessor();
  processor.process();
}
Advanced
85. How does Rabin-Karp String Matching work in Dart?

Rabin-Karp uses rolling hashes for efficient string matching, ideal for multiple pattern search in text.

  • Rolling Hash: Efficient hash updates
  • Pattern Preprocessing: Compute pattern hash
  • Average O(n): Efficient for long texts
  • Applications: Plagiarism detection, DNA
dart
// Rabin-Karp String Matching in Dart
List<int> rabinKarp(String text, String pattern) {
  List<int> positions = [];
  int n = text.length, m = pattern.length;
  const int base = 31;
  const int mod = 1000000009;

  // Compute hash of pattern and first window
  int patHash = 0, winHash = 0, power = 1;

  for (int i = 0; i < m; i++) {
    patHash = (patHash + (text.codeUnitAt(i) - 96) * power) % mod;
    winHash = (winHash + (text.codeUnitAt(i) - 96) * power) % mod;
    if (i < m - 1) power = (power * base) % mod;
  }

  for (int i = 0; i <= n - m; i++) {
    if (patHash == winHash) {
      if (text.substring(i, i + m) == pattern) {
        positions.add(i);
      }
    }
    if (i < n - m) {
      winHash = (winHash - (text.codeUnitAt(i) - 96) + mod) % mod;
      winHash = (winHash * (mod + 1 - base)) % mod;
      winHash = (winHash + (text.codeUnitAt(i + m) - 96) * power) % mod;
    }
  }
  return positions;
}

void main() {
  String text = 'aabaacaadaabaaba';
  String pattern = 'aaba';
  List<int> pos = rabinKarp(text, pattern);
  print('Rabin-Karp found at: ${pos.join(' ')}');
}
Advanced
86. How does Dynamic type work in Dart?

Dynamic type in Dart allows runtime type flexibility, enabling dynamic objects and runtime type checking.

  • Dynamic Type: Runtime type checking
  • Dynamic Objects: Maps as dynamic structures
  • Type Flexibility: Can hold any type
  • Applications: Dynamic systems, JSON parsing
dart
// Dynamic in Dart
void main() {
  // dynamic type
  dynamic value = 42;
  print('Int: $value');
  value = 'Hello, World!';
  print('String: $value');
  value = 3.14159;
  print('Double: $value');

  // Dynamic object with Map
  Map<String, dynamic> person = {};
  person['name'] = 'Alice';
  person['age'] = 25;
  print('Hello, I'm ${person['name']}');

  // Dictionary to dynamic
  Map<String, dynamic> dict = {
    'Name': 'Bob',
    'Age': 30
  };
  print('${dict['Name']} is ${dict['Age']} years old');

  // Type checking
  print('value is int: ${value is int}');
  print('value is double: ${value is double}');

  // Generic with type parameter
  void printType<T>(T val) {
    print('Type: ${T}, Value: $val');
  }

  printType<int>(42);
  printType<String>('hello');
  printType<double>(3.14);
}
Advanced
87. How do Mixins and Interfaces work in Dart?

Mixins and Interfaces provide powerful code reuse and contract enforcement in Dart's type system.

  • Mixins: Code reuse across hierarchies
  • Interfaces: Contract definition
  • Implementation: Multiple interface support
  • Applications: Plugin architectures, frameworks
dart
// Mixins and Interfaces
// Interface for printable
abstract class Printable {
  void print();
}

// Interface for comparable
abstract class Comparable<T> {
  int compareTo(T other);
}

// Mixin
mixin PrintableMixin {
  void printWithHeader() {
    print('=== Print Start ===');
    print();
    print('=== Print End ===');
  }
}

// Implementation
class Point with PrintableMixin implements Printable, Comparable<Point> {
  double x, y;

  Point(this.x, this.y);

  @override
  void print() {
    print('Point($x, $y)');
  }

  @override
  int compareTo(Point other) {
    double d1 = x * x + y * y;
    double d2 = other.x * other.x + other.y * other.y;
    return d1.compareTo(d2);
  }

  double get distance => x * x + y * y;
}

void main() {
  Point p1 = Point(3, 4);
  Point p2 = Point(1, 1);
  Point p3 = Point(3, 4);

  p1.print();
  p1.printWithHeader();

  print('p1 == p3: ${p1.compareTo(p3) == 0}');
  print('p1 > p2: ${p1.compareTo(p2) > 0}');
  print('p2 < p1: ${p2.compareTo(p1) < 0}');

  // With functional methods
  List<Point> points = [p1, p2, p3];
  var sorted = points..sort((a, b) => a.distance.compareTo(b.distance));
  print('Sorted by distance:');
  for (var p in sorted) {
    p.print();
  }
}
Advanced
88. What is Producer-Consumer concurrency in Dart?

Producer-Consumer pattern coordinates multiple threads/tasks producing and consuming items from a bounded buffer.

  • Bounded Buffer: Limited capacity queue
  • Synchronization: Blocking when full/empty
  • Thread Safety: Avoid race conditions
  • Applications: Task queues, data pipelines
dart
// Concurrency - Producer-Consumer
import 'dart:async';

class BoundedBuffer {
  List<int> _buffer = [];
  int _capacity;
  Completer<void>? _notFull;
  Completer<void>? _notEmpty;

  BoundedBuffer(this._capacity) {
    _notFull = Completer<void>()..complete();
    _notEmpty = Completer<void>();
  }

  Future<void> produce(int item) async {
    await _notFull!.future;
    _notFull = Completer<void>();
    _buffer.add(item);
    print('Produced: $item | Buffer size: ${_buffer.length}');
    _notEmpty!.complete();
  }

  Future<int> consume() async {
    await _notEmpty!.future;
    _notEmpty = Completer<void>();
    int item = _buffer.removeAt(0);
    print('Consumed: $item | Buffer size: ${_buffer.length}');
    if (_buffer.length < _capacity) {
      _notFull!.complete();
    }
    return item;
  }
}

void main() async {
  BoundedBuffer bb = BoundedBuffer(3);

  // Producer
  Future<void> producer() async {
    for (int i = 1; i <= 6; i++) {
      await bb.produce(i);
    }
  }

  // Consumer
  Future<void> consumer() async {
    for (int i = 0; i < 6; i++) {
      await bb.consume();
    }
  }

  await Future.wait([producer(), consumer()]);
}
Advanced
89. What are Records and Pattern Matching in Dart?

Records provide lightweight data grouping. Pattern Matching enables powerful destructuring and type-based logic.

  • Positional Records: Position-based access
  • Named Records: Field-based access
  • Pattern Matching: Switch statements
  • Deconstruction: Extract record values
dart
// Dart Features - Records and Pattern Matching
// Record
record Person(String name, int age);

// Record with methods
record Student(String name, int age, String major) {
  void display() {
    print('$name ($age) studies $major');
  }
}

// Positional record with deconstruction
record Point(double x, double y) {
  double get distance => Math.sqrt(x * x + y * y);
}

void main() {
  // Record instantiation
  Person p1 = Person('Alice', 25);
  Person p2 = Person('Alice', 25);
  Person p3 = Person(p1.name, p1.age + 1);

  print('p1 == p2: ${p1 == p2}');
  print('p1: Person(name: Alice, age: 25)');
  print('p3: Person(name: Alice, age: 26)');

  // Pattern matching
  dynamic obj = 42;
  if (obj is int && obj > 10) {
    print('Medium int');
  } else if (obj is int) {
    print('Small int');
  } else if (obj is String) {
    print('String: $obj');
  }

  // Property pattern
  if (p1 is Person && p1.name == 'Alice' && p1.age == 25) {
    print('Matched Alice, age 25');
  }

  // Tuple pattern
  var (x, y) = (10, 20);
  switch ((x, y)) {
    case (0, 0):
      print('Origin');
    case (10, 20):
      print('Equal');
    default:
      print('Other');
  }
}
Advanced
90. What are Advanced Dart Features for Performance and Memory?

Advanced Dart Features for performance include typed data, slicing, pooling, and memory management techniques.

  • Typed Data: Uint8List, ByteData
  • Slicing: Efficient view of data
  • Pooling: Object reuse patterns
  • Memory Management: ReadOnly collections
dart
// Advanced Dart - Performance and Memory
import 'dart:typed_data';

void main() {
  // Uint8List (similar to Span)
  Uint8List numbers = Uint8List.fromList([1, 2, 3, 4, 5]);
  print('Numbers: ${numbers.join(', ')}');

  // Slice
  var slice = numbers.sublist(1, 4);
  print('Slice: ${slice.join(', ')}');

  // Modify slice affects original
  slice[0] = 99;
  print('After slice modification: ${numbers.join(', ')}');

  // Memory
  List<int> memory = [10, 20, 30, 40, 50];
  var memorySlice = memory.sublist(1, 4);
  print('Memory slice: ${memorySlice.join(', ')}');

  // Pool (using List)
  List<int> pooled = List.filled(10, 0);
  for (int i = 0; i < 10; i++) {
    pooled[i] = i * 2;
  }
  print('Pooled: ${pooled.join(', ')}');

  // ByteData
  ByteData bytes = ByteData(4);
  bytes.setInt32(0, 0x01020304);
  int intValue = bytes.getInt32(0);
  print('Bytes as int: $intValue');

  // String creation
  String text = '**********';
  print('Created: $text');

  // ReadOnlyList
  List<int> readOnly = List.unmodifiable([1, 2, 3, 4, 5]);
  print('ReadOnly: ${readOnly.join(', ')}');
}
Advanced
91. How does Reflection work in Dart?

Reflection in Dart provides runtime introspection of types, methods, and fields using the mirrors library.

  • Class Mirrors: Reflect on classes
  • Instance Mirrors: Reflect on instances
  • Method Invocation: Dynamic method calls
  • Access Private Members: Reflection capabilities
dart
// Reflection in Dart
import 'dart:mirrors';

class Calculator {
  int add(int a, int b) => a + b;
  int multiply(int a, int b) => a * b;

  String _secret = 'Hidden';

  String getSecret() => _secret;

  void printMessage(String message) => print(message);
}

void main() {
  ClassMirror calcType = reflectClass(Calculator);

  // Create instance
  InstanceMirror calc = calcType.newInstance(const Symbol(''), []);

  // Get and invoke method
  MethodMirror addMethod = calcType.declarations[const Symbol('add')] as MethodMirror;
  var result = calc.invoke(addMethod, [5, 3]);
  print('Add(5,3) = ${result.reflectee}');

  // Get all methods
  print('\nAll methods:');
  for (var declaration in calcType.declarations.values) {
    if (declaration is MethodMirror) {
      print('  ${declaration.simpleName} (${declaration.isPrivate ? 'private' : 'public'})');
    }
  }

  // Access private field
  VariableMirror secretField = calcType.declarations[const Symbol('_secret')] as VariableMirror;
  String secret = calc.getField(secretField.simpleName).reflectee;
  print('Private field: $secret');

  // Invoke private method
  MethodMirror getSecretMethod = calcType.declarations[const Symbol('getSecret')] as MethodMirror;
  String secretValue = calc.invoke(getSecretMethod, []).reflectee;
  print('Private method: $secretValue');

  // Dynamic invocation with delegate
  Function addDelegate = (int a, int b) => calc.reflectee.add(a, b);
  print('Delegate: ${addDelegate(10, 20)}');
}
Advanced
92. What are Advanced Functional Queries in Dart?

Advanced Functional Queries enable building dynamic queries, sorting, projections, and grouping on collections.

  • Dynamic Filtering: Runtime query building
  • Dynamic Ordering: Field-based sorting
  • Projections: Field selection
  • Grouping: Dynamic group-by operations
dart
// Advanced Functional Queries
class Person {
  String name;
  int age;
  String city;

  Person(this.name, this.age, this.city);
}

void main() {
  List<Person> data = [
    Person('Alice', 25, 'NYC'),
    Person('Bob', 30, 'LA'),
    Person('Carol', 22, 'NYC'),
    Person('Dave', 35, 'Chicago')
  ];

  // Dynamic query building
  bool filter(Person p) => p.age > 25 && p.city == 'NYC';
  var result = data.where(filter).toList();
  print('Filter result: ${result.map((p) => p.name).join(', ')}');

  // Dynamic ordering
  String sortField = 'age';
  var sorted = data.toList()
    ..sort((a, b) => a.age.compareTo(b.age));
  print('Sorted by Age: ${sorted.map((p) => '${p.name}(${p.age})').join(', ')}');

  // Dynamic select
  List<String> fields = ['name', 'city'];
  print('Projections:');
  for (var p in data) {
    var values = fields.map((f) {
      switch (f) {
        case 'name': return p.name;
        case 'city': return p.city;
        default: return null;
      }
    }).join(', ');
    print('  $values');
  }

  // Group by dynamic
  var grouped = data.fold<Map<String, List<Person>>>({}, (map, p) {
    map.putIfAbsent(p.city, () => []).add(p);
    return map;
  });
  grouped.forEach((city, people) {
    print('City: $city (${people.length})');
  });
}
Advanced
93. How do you implement a Bank Account System in Dart?

A Bank Account System demonstrates object-oriented programming concepts including encapsulation, transactions, and state management.

  • Encapsulation: Private fields with public methods
  • Transactions: Record all account operations
  • Balance Management: Deposit and withdraw operations
  • Statement Generation: Print transaction history
dart
// Complete Bank Account System in Dart
class BankAccount {
  static int _nextId = 1000;
  String accountId;
  String owner;
  double balance;
  List<Transaction> transactions = [];

  BankAccount(this.owner, [double initialDeposit = 0.0]) {
    _nextId++;
    accountId = 'ACC$_nextId';
    balance = 0.0;
    if (initialDeposit > 0) deposit(initialDeposit, 'Initial deposit');
  }

  void deposit(double amount, [String description = 'Deposit']) {
    if (amount <= 0) throw ArgumentError('Deposit amount must be positive');
    balance += amount;
    transactions.add(Transaction('DEPOSIT', amount, description, balance));
  }

  void withdraw(double amount, [String description = 'Withdrawal']) {
    if (amount <= 0) throw ArgumentError('Withdrawal amount must be positive');
    if (amount > balance) throw ArgumentError('Insufficient funds');
    balance -= amount;
    transactions.add(Transaction('WITHDRAWAL', amount, description, balance));
  }

  double getBalance() => balance;

  void printStatement() {
    print('=== Account Statement for $accountId ===');
    print('Owner: $owner');
    print('Balance: $${balance.toStringAsFixed(2)}');
    print('Transactions:');
    for (var t in transactions) {
      print('  ${t.toString()}');
    }
  }
}

class Transaction {
  String type;
  double amount;
  String description;
  double balance;

  Transaction(this.type, this.amount, this.description, this.balance);

  @override
  String toString() {
    return '$type: $${amount.toStringAsFixed(2)} - $description (Balance: $${balance.toStringAsFixed(2)})';
  }
}

void main() {
  BankAccount acc = BankAccount('Alice', 1000);
  acc.deposit(500, 'Salary');
  acc.withdraw(200, 'Groceries');
  acc.deposit(100, 'Bonus');
  acc.withdraw(50, 'Coffee');
  acc.printStatement();
}
Advanced
94. What is Event-Driven Programming in Dart?

Event-Driven Programming uses events to trigger behavior. Dart's EventEmitter pattern enables loose coupling between components.

  • Event Emitter: Central event management
  • Subscribers: Listen for specific events
  • Event Handling: Respond to events with callbacks
  • Memory Management: Proper cleanup of event listeners
dart
// Event-Driven Programming in Dart
class EventEmitter {
  Map<String, List<Function>> _listeners = {};

  void on(String event, Function handler) {
    _listeners.putIfAbsent(event, () => []).add(handler);
  }

  void emit(String event, [dynamic data]) {
    if (_listeners.containsKey(event)) {
      for (var handler in _listeners[event]!) {
        handler(data);
      }
    }
  }

  void off(String event, [Function? handler]) {
    if (handler == null) {
      _listeners.remove(event);
    } else if (_listeners.containsKey(event)) {
      _listeners[event]!.removeWhere((h) => h == handler);
    }
  }
}

void main() {
  EventEmitter emitter = EventEmitter();

  // Subscribe to events
  emitter.on('userLogin', (data) {
    print('User logged in: $data');
  });

  emitter.on('userLogout', (data) {
    print('User logged out: $data');
  });

  emitter.on('dataUpdate', (data) {
    print('Data updated: ${data['message']}');
  });

  // Emit events
  emitter.emit('userLogin', 'Alice');
  emitter.emit('dataUpdate', {'message': 'Profile updated', 'timestamp': DateTime.now()});
  emitter.emit('userLogout', 'Alice');

  // Remove specific handler
  void handler(data) => print('Special handler: $data');
  emitter.on('special', handler);
  emitter.emit('special', 'Hello');
  emitter.off('special', handler);
  emitter.emit('special', 'This won't print');
}
Advanced
95. How do Custom Streams and StreamControllers work in Dart?

Streams provide asynchronous data flow. StreamControllers allow creating and controlling custom streams with full lifecycle management.

  • Stream: Asynchronous data sequence
  • StreamController: Create and manage streams
  • Subscription: Listen to stream events
  • Broadcast Streams: Multiple subscribers
dart
// Custom Stream and StreamController in Dart
import 'dart:async';

class NumberStream {
  StreamController<int> _controller = StreamController<int>();

  Stream<int> get stream => _controller.stream;

  void generateNumbers(int count) async {
    for (int i = 1; i <= count; i++) {
      await Future.delayed(Duration(milliseconds: 500));
      _controller.add(i);
    }
    _controller.close();
  }

  void dispose() {
    _controller.close();
  }
}

void main() async {
  NumberStream ns = NumberStream();

  // Subscribe to stream
  StreamSubscription sub = ns.stream.listen(
    (data) => print('Received: $data'),
    onError: (error) => print('Error: $error'),
    onDone: () => print('Stream completed'),
    cancelOnError: true
  );

  // Start generating
  ns.generateNumbers(5);

  // Cancel after 2 seconds
  await Future.delayed(Duration(seconds: 2));
  await sub.cancel();
  print('Subscription cancelled');

  // Transform stream
  Stream<int> evenStream = ns.stream.where((n) => n.isEven);
  evenStream.listen((data) => print('Even: $data'));

  // Multiple subscribers
  Stream<int> shared = ns.stream.asBroadcastStream();
  shared.listen((data) => print('Sub1: $data'));
  shared.listen((data) => print('Sub2: $data'));

  ns.dispose();
}
Advanced
96. How do you make HTTP Requests and scrape data in Dart?

HTTP Requests and Web Scraping are essential for data retrieval. Dart provides HttpClient for making HTTP requests and parsing responses.

  • GET Requests: Fetch data from APIs
  • POST Requests: Send data to servers
  • JSON Parsing: Convert JSON to Dart objects
  • Error Handling: Handle HTTP errors gracefully
dart
// Web Scraping and HTTP Requests in Dart
import 'dart:convert';
import 'dart:io';

class HttpClient {
  static Future<String> get(String url) async {
    var client = HttpClient();
    try {
      var request = await client.getUrl(Uri.parse(url));
      var response = await request.close();
      if (response.statusCode == 200) {
        return await response.transform(utf8.decoder).join();
      } else {
        throw Exception('HTTP Error: ${response.statusCode}');
      }
    } finally {
      client.close();
    }
  }

  static Future<String> post(String url, Map<String, dynamic> data) async {
    var client = HttpClient();
    try {
      var request = await client.postUrl(Uri.parse(url));
      request.headers.set('Content-Type', 'application/json');
      request.add(utf8.encode(jsonEncode(data)));
      var response = await request.close();
      if (response.statusCode == 200 || response.statusCode == 201) {
        return await response.transform(utf8.decoder).join();
      } else {
        throw Exception('HTTP Error: ${response.statusCode}');
      }
    } finally {
      client.close();
    }
  }
}

void main() async {
  try {
    // GET request
    print('Fetching data...');
    String response = await HttpClient.get('https://jsonplaceholder.typicode.com/posts/1');
    Map<String, dynamic> post = jsonDecode(response);
    print('Post: ${post['title']}');
    print('Body: ${post['body']}');

    // POST request
    Map<String, dynamic> newPost = {
      'title': 'My New Post',
      'body': 'This is the content of my new post',
      'userId': 1
    };
    String result = await HttpClient.post(
      'https://jsonplaceholder.typicode.com/posts',
      newPost
    );
    print('Created: $result');
  } catch (e) {
    print('Error: $e');
  }
}
Advanced
97. How do you perform Database Operations in Dart?

Database Operations with SQLite in Dart provide persistent storage. The sqflite package offers a comprehensive SQL API for CRUD operations.

  • SQLite: Embedded database engine
  • CRUD Operations: Create, Read, Update, Delete
  • Transactions: Atomic database operations
  • Migration: Schema evolution and versioning
dart
// Database Operations with SQLite in Dart
import 'dart:async';
import 'dart:io';
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';

class User {
  int? id;
  String name;
  String email;
  int age;

  User({this.id, required this.name, required this.email, required this.age});

  Map<String, dynamic> toMap() {
    return {
      'id': id,
      'name': name,
      'email': email,
      'age': age,
    };
  }

  factory User.fromMap(Map<String, dynamic> map) {
    return User(
      id: map['id'],
      name: map['name'],
      email: map['email'],
      age: map['age'],
    );
  }
}

class DatabaseHelper {
  static final DatabaseHelper _instance = DatabaseHelper._internal();
  factory DatabaseHelper() => _instance;
  DatabaseHelper._internal();

  Database? _database;

  Future<Database> get database async {
    if (_database != null) return _database!;
    _database = await _initDatabase();
    return _database!;
  }

  Future<Database> _initDatabase() async {
    String path = join(await getDatabasesPath(), 'users.db');
    return await openDatabase(
      path,
      version: 1,
      onCreate: _onCreate,
    );
  }

  Future<void> _onCreate(Database db, int version) async {
    await db.execute('''
      CREATE TABLE users(
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT NOT NULL,
        email TEXT UNIQUE NOT NULL,
        age INTEGER
      )
    ''');
    print('Database created');
  }

  Future<int> insertUser(User user) async {
    Database db = await database;
    return await db.insert('users', user.toMap());
  }

  Future<List<User>> getUsers() async {
    Database db = await database;
    final List<Map<String, dynamic>> maps = await db.query('users');
    return List.generate(maps.length, (i) => User.fromMap(maps[i]));
  }

  Future<int> updateUser(User user) async {
    Database db = await database;
    return await db.update(
      'users',
      user.toMap(),
      where: 'id = ?',
      whereArgs: [user.id],
    );
  }

  Future<int> deleteUser(int id) async {
    Database db = await database;
    return await db.delete(
      'users',
      where: 'id = ?',
      whereArgs: [id],
    );
  }

  Future<void> close() async {
    if (_database != null) {
      await _database!.close();
      _database = null;
    }
  }
}

void main() async {
  DatabaseHelper db = DatabaseHelper();

  try {
    // Insert users
    User user1 = User(name: 'Alice', email: 'alice@email.com', age: 25);
    User user2 = User(name: 'Bob', email: 'bob@email.com', age: 30);
    
    int id1 = await db.insertUser(user1);
    int id2 = await db.insertUser(user2);
    print('Inserted users with IDs: $id1, $id2');

    // Query users
    List<User> users = await db.getUsers();
    print('All users:');
    for (var u in users) {
      print('  ${u.id}. ${u.name} (${u.email}) - Age: ${u.age}');
    }

    // Update user
    User userToUpdate = users.first;
    userToUpdate.age = 26;
    await db.updateUser(userToUpdate);
    print('Updated user ${userToUpdate.name}');

    // Delete user
    await db.deleteUser(users.last.id!);
    print('Deleted last user');

    // Show final list
    users = await db.getUsers();
    print('Final users:');
    for (var u in users) {
      print('  ${u.name} (${u.email})');
    }
  } catch (e) {
    print('Error: $e');
  } finally {
    await db.close();
  }
}
Advanced
98. How do you write Unit Tests in Dart?

Unit Testing ensures code quality and correctness. Dart provides a built-in testing framework with assertions, test groups, and async support.

  • Assertions: Verify expected results
  • Test Cases: Individual test scenarios
  • Setup/Teardown: Test lifecycle management
  • Async Testing: Test asynchronous code
dart
// Unit Testing in Dart
import 'dart:async';

class Calculator {
  int add(int a, int b) => a + b;
  int subtract(int a, int b) => a - b;
  int multiply(int a, int b) => a * b;
  double divide(int a, int b) {
    if (b == 0) throw ArgumentError('Division by zero');
    return a / b;
  }

  Future<int> asyncAdd(int a, int b) async {
    await Future.delayed(Duration(milliseconds: 100));
    return a + b;
  }
}

// Test file would normally be in a separate file
void runTests() {
  Calculator calc = Calculator();

  // Test 1: Addition
  assert(calc.add(2, 3) == 5, 'Add test failed');
  print('✓ Add test passed');

  // Test 2: Subtraction
  assert(calc.subtract(5, 3) == 2, 'Subtract test failed');
  print('✓ Subtract test passed');

  // Test 3: Multiplication
  assert(calc.multiply(4, 3) == 12, 'Multiply test failed');
  print('✓ Multiply test passed');

  // Test 4: Division
  assert(calc.divide(10, 2) == 5.0, 'Divide test failed');
  print('✓ Divide test passed');

  // Test 5: Division by zero
  try {
    calc.divide(5, 0);
    assert(false, 'Division by zero should throw');
  } catch (e) {
    assert(e is ArgumentError, 'Wrong exception type');
    print('✓ Division by zero test passed');
  }

  // Test 6: Async addition
  calc.asyncAdd(5, 3).then((result) {
    assert(result == 8, 'Async add test failed');
    print('✓ Async add test passed');
  });

  print('All tests passed!');
}

void main() {
  runTests();
  print('
=== Test Results ===');
  print('All tests completed successfully');
}
Advanced
99. What are Factory and Abstract Factory Design Patterns in Dart?

Factory and Abstract Factory are creational design patterns that provide interfaces for creating families of related objects without specifying concrete classes.

  • Factory Method: Single product creation
  • Abstract Factory: Family of related products
  • Decoupling: Separate creation from usage
  • Product Families: Consistent product variants
dart
// Design Patterns - Factory and Abstract Factory
// Product interfaces
abstract class Button {
  void render();
  void onClick();
}

abstract class Checkbox {
  void render();
  void onCheck();
}

// Concrete products for Windows
class WindowsButton implements Button {
  @override
  void render() => print('Rendering Windows button');
  @override
  void onClick() => print('Windows button clicked');
}

class WindowsCheckbox implements Checkbox {
  @override
  void render() => print('Rendering Windows checkbox');
  @override
  void onCheck() => print('Windows checkbox checked');
}

// Concrete products for Mac
class MacButton implements Button {
  @override
  void render() => print('Rendering Mac button');
  @override
  void onClick() => print('Mac button clicked');
}

class MacCheckbox implements Checkbox {
  @override
  void render() => print('Rendering Mac checkbox');
  @override
  void onCheck() => print('Mac checkbox checked');
}

// Abstract Factory
abstract class GUIFactory {
  Button createButton();
  Checkbox createCheckbox();
}

// Concrete factories
class WindowsFactory implements GUIFactory {
  @override
  Button createButton() => WindowsButton();
  @override
  Checkbox createCheckbox() => WindowsCheckbox();
}

class MacFactory implements GUIFactory {
  @override
  Button createButton() => MacButton();
  @override
  Checkbox createCheckbox() => MacCheckbox();
}

// Application
class Application {
  final GUIFactory factory;

  Application(this.factory);

  void renderUI() {
    Button button = factory.createButton();
    Checkbox checkbox = factory.createCheckbox();

    button.render();
    checkbox.render();
  }
}

void main() {
  // Windows app
  Application windowsApp = Application(WindowsFactory());
  print('=== Windows Application ===');
  windowsApp.renderUI();

  // Mac app
  Application macApp = Application(MacFactory());
  print('
=== Mac Application ===');
  macApp.renderUI();
}
Advanced
100. How does Flutter-like State Management work in Dart?

State Management is crucial for reactive applications. This example demonstrates a Flutter-like state management pattern with reactive updates and widget hierarchy.

  • State Class: Managed state with listeners
  • Widgets: UI components that react to state
  • Notification System: Update UI on state changes
  • Cleanup: Proper resource disposal
dart
// Flutter-like State Management in Dart
import 'dart:async';

// State class
class State<T> {
  T value;
  List<Function> _listeners = [];

  State(this.value);

  T get state => value;

  void setState(T newValue) {
    value = newValue;
    _notifyListeners();
  }

  void addListener(Function listener) {
    _listeners.add(listener);
  }

  void removeListener(Function listener) {
    _listeners.remove(listener);
  }

  void _notifyListeners() {
    for (var listener in _listeners) {
      listener();
    }
  }

  void dispose() {
    _listeners.clear();
  }
}

// Counter App
class CounterApp {
  State<int> counter = State<int>(0);
  List<Widget> widgets = [];

  CounterApp() {
    // Create widgets
    widgets.add(TextWidget('Counter: ${counter.state}'));
    widgets.add(ButtonWidget('Increment', () => counter.setState(counter.state + 1)));
    widgets.add(ButtonWidget('Decrement', () => counter.setState(counter.state - 1)));
    widgets.add(ButtonWidget('Reset', () => counter.setState(0)));

    // Listen to state changes
    counter.addListener(() {
      print('Counter updated: ${counter.state}');
      updateUI();
    });
  }

  void updateUI() {
    print('=== UI Update ===');
    print('Counter: ${counter.state}');
  }

  void run() {
    print('Counter App Started');
    updateUI();

    // Simulate user interactions
    Future.delayed(Duration(seconds: 1), () {
      print('User clicks Increment');
      counter.setState(counter.state + 1);
    });

    Future.delayed(Duration(seconds: 2), () {
      print('User clicks Increment');
      counter.setState(counter.state + 1);
    });

    Future.delayed(Duration(seconds: 3), () {
      print('User clicks Decrement');
      counter.setState(counter.state - 1);
    });

    Future.delayed(Duration(seconds: 4), () {
      print('User clicks Reset');
      counter.setState(0);
    });
  }

  void dispose() {
    counter.dispose();
  }
}

// Simple Widgets
class TextWidget {
  String text;
  TextWidget(this.text) {
    print('Text: $text');
  }
}

class ButtonWidget {
  String label;
  Function onPressed;

  ButtonWidget(this.label, this.onPressed) {
    print('Button: $label');
  }

  void click() {
    onPressed();
  }
}

void main() {
  CounterApp app = CounterApp();
  app.run();

  // Keep app running for a while
  Future.delayed(Duration(seconds: 6), () {
    print('
App closing...');
    app.dispose();
  });
}