-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a68a0fb
commit f8a717d
Showing
4 changed files
with
174 additions
and
0 deletions.
There are no files selected for viewing
99 changes: 99 additions & 0 deletions
99
lib/22_greedy_algorithm_fractional_knapsack_problem_algorithm_code/fractional_knapsack.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ environment: | |
|
||
dependencies: | ||
collection: ^1.17.2 | ||
equatable: ^2.0.5 | ||
|
||
dev_dependencies: | ||
lints: ^2.0.0 | ||
|
66 changes: 66 additions & 0 deletions
66
...greedy_algorithm_fractional_knapsack_problem_algorithm_code/fractional_knapsack_test.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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), | ||
], | ||
); | ||
}, | ||
); | ||
}); | ||
} |