Skip to content

Commit

Permalink
feat: ✨ add the code of video 22
Browse files Browse the repository at this point in the history
  • Loading branch information
moazelsawaf committed Jun 25, 2023
1 parent a68a0fb commit f8a717d
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import 'package:collection/collection.dart';
import 'package:equatable/equatable.dart';

class Item extends Equatable {
final String name;
final double ratio;
final double value;
final double weight;

Item({
required this.name,
required this.value,
required this.weight,
}) : ratio = value / weight;

@override
String toString() {
return '$name\t$value\t$weight\t$ratio';
}

// Include all the properties in the equality operation
@override
List<Object?> get props => [name, value, weight, ratio];
}

class Knapsack {
final double maxCapacity;
double currentCapacity = 0;
double totalValue = 0;
List<Item> items = [];

Knapsack({required this.maxCapacity});

void _addItem(Item newItem) {
if (newItem.weight > maxCapacity - currentCapacity) {
final weightDiff = maxCapacity - currentCapacity;

final item = Item(
name: newItem.name,
value: newItem.ratio * weightDiff,
weight: weightDiff,
);

newItem = item;
}

items.add(newItem);
currentCapacity += newItem.weight;
totalValue += newItem.value;
}

void addItems(List<Item> newItems) {
int j = 0;

while (currentCapacity < maxCapacity) {
_addItem(newItems[j]);
j++;
}
}
}

List<Item> mergeSort(List<Item> items) {
if (items.length == 1) return items;

final mid = items.length ~/ 2;

List<Item> left = items.slice(0, mid).toList();
List<Item> right = items.slice(mid).toList();

left = mergeSort(left);
right = mergeSort(right);
return _merge(left, right);
}

List<Item> _merge(List<Item> left, List<Item> right) {
final result = <Item>[];

while (left.isNotEmpty && right.isNotEmpty) {
if (left.first.ratio < right.first.ratio) {
result.add(right.first);
right = right.slice(1).toList();
} else {
result.add(left.first);
left = left.slice(1).toList();
}
}

while (left.isNotEmpty) {
result.add(left.first);
left = left.slice(1).toList();
}

while (right.isNotEmpty) {
result.add(right.first);
right = right.slice(1).toList();
}

return result;
}
8 changes: 8 additions & 0 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.3"
equatable:
dependency: "direct main"
description:
name: equatable
sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2
url: "https://pub.dev"
source: hosted
version: "2.0.5"
file:
dependency: transitive
description:
Expand Down
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ environment:

dependencies:
collection: ^1.17.2
equatable: ^2.0.5

dev_dependencies:
lints: ^2.0.0
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import 'package:test/test.dart';

import 'package:cloudnativebasecamp_algo_01_dart/22_greedy_algorithm_fractional_knapsack_problem_algorithm_code/fractional_knapsack.dart';

void main() {
group('Fractional Knapsack', () {
// NOTE: The same test data in the video
test(
'with 6 items and weight of 12',
() async {
final items = [
Item(name: '#0', value: 4, weight: 1),
Item(name: '#1', value: 9, weight: 2),
Item(name: '#2', value: 12, weight: 10),
Item(name: '#3', value: 11, weight: 4),
Item(name: '#4', value: 6, weight: 3),
Item(name: '#5', value: 5, weight: 5),
];
final sortedItems = mergeSort(items);
final knapsack = Knapsack(maxCapacity: 12);

knapsack.addItems(sortedItems);

expect(12, knapsack.currentCapacity);
expect(32.4, knapsack.totalValue);
expect(
knapsack.items,
[
Item(name: '#1', value: 9, weight: 2),
Item(name: '#0', value: 4, weight: 1),
Item(name: '#3', value: 11, weight: 4),
Item(name: '#4', value: 6, weight: 3),
Item(name: '#2', value: 2.4, weight: 2),
],
);
},
);

test(
'with 4 items and weight of 40',
() async {
final items = [
Item(name: '#0', value: 10, weight: 30),
Item(name: '#1', value: 20, weight: 10),
Item(name: '#2', value: 30, weight: 40),
Item(name: '#3', value: 40, weight: 20),
];
final sortedItems = mergeSort(items);
final knapsack = Knapsack(maxCapacity: 40);

knapsack.addItems(sortedItems);

expect(40, knapsack.currentCapacity);
expect(67.5, knapsack.totalValue);
expect(
knapsack.items,
[
Item(name: '#1', value: 20, weight: 10),
Item(name: '#3', value: 40, weight: 20),
Item(name: '#2', value: 7.5, weight: 10),
],
);
},
);
});
}

0 comments on commit f8a717d

Please sign in to comment.