Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 10a798c

Browse files
committedJun 1, 2019
New Algorithm
- Created QuickSort algorithm Feature: Restart Swaps - new dataSourceBackup, to store the original dataSource - new restart function, that restore dataSource then generate and start all swaps after 1 second. - handle the restart button after end all swaps - add new parameter to AlgorithmDetailView protocol, to handle if it need to reload the collection view or not. Feature: Random Sample Array - New button to allow user to use a Random sample array.
1 parent b22d2e3 commit 10a798c

File tree

12 files changed

+203
-20
lines changed

12 files changed

+203
-20
lines changed
 

‎SortingAlgorithms.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
147EBB4E22A2196A00D19988 /* QuickSort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 147EBB4D22A2196A00D19988 /* QuickSort.swift */; };
1011
712E1385225585B100EFBAC9 /* AlgorithmsListProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 712E1384225585B100EFBAC9 /* AlgorithmsListProtocols.swift */; };
1112
712E13872255874B00EFBAC9 /* AlgorithmsListPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 712E13862255874B00EFBAC9 /* AlgorithmsListPresenter.swift */; };
1213
712E138B22558AE200EFBAC9 /* UICollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 712E138A22558AE200EFBAC9 /* UICollectionViewCell.swift */; };
@@ -48,6 +49,7 @@
4849
/* End PBXContainerItemProxy section */
4950

5051
/* Begin PBXFileReference section */
52+
147EBB4D22A2196A00D19988 /* QuickSort.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSort.swift; sourceTree = "<group>"; };
5153
712E1384225585B100EFBAC9 /* AlgorithmsListProtocols.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlgorithmsListProtocols.swift; sourceTree = "<group>"; };
5254
712E13862255874B00EFBAC9 /* AlgorithmsListPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlgorithmsListPresenter.swift; sourceTree = "<group>"; };
5355
712E138A22558AE200EFBAC9 /* UICollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UICollectionViewCell.swift; sourceTree = "<group>"; };
@@ -166,6 +168,7 @@
166168
716548AD2254EED8009C41DD /* BubbleSort.swift */,
167169
716548AF22554791009C41DD /* InsertionSort.swift */,
168170
716548B9225551E6009C41DD /* SelectionSort.swift */,
171+
147EBB4D22A2196A00D19988 /* QuickSort.swift */,
169172
);
170173
path = Algorithms;
171174
sourceTree = "<group>";
@@ -373,6 +376,7 @@
373376
716548BA225551E6009C41DD /* SelectionSort.swift in Sources */,
374377
712E13872255874B00EFBAC9 /* AlgorithmsListPresenter.swift in Sources */,
375378
716548B822554DDD009C41DD /* AlgorithmDetailCell.swift in Sources */,
379+
147EBB4E22A2196A00D19988 /* QuickSort.swift in Sources */,
376380
712E138B22558AE200EFBAC9 /* UICollectionViewCell.swift in Sources */,
377381
716548AE2254EED8009C41DD /* BubbleSort.swift in Sources */,
378382
716548B4225548B7009C41DD /* AlgorithmDetailProtocol.swift in Sources */,
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//
2+
// QuickSort.swift
3+
// SortingAlgorithms
4+
//
5+
// Created by Joao Reichert on 31/05/19.
6+
// Copyright © 2019 Victor. All rights reserved.
7+
//
8+
9+
import Foundation
10+
11+
final class QuickSort: Algorithm {
12+
13+
final var title: String = "Quick Sort"
14+
final var image: String = "ic_quick_sorting"
15+
final var description: String = "Quick Sort Description"
16+
17+
private var swaps = [(x0: Int, x1: Int)]()
18+
19+
final func generateSwaps(from list: [Int]) -> [(x0: Int, x1: Int)] {
20+
swaps.removeAll()
21+
guard list.count > 1 else { return [] }
22+
23+
var copy = list;
24+
quicksort(array: &copy, left: 0, right: list.count - 1);
25+
26+
return swaps
27+
}
28+
}
29+
30+
extension QuickSort {
31+
32+
private func swap(array: inout [Int], num1: Int, num2: Int) {
33+
array.swapAt(num1, num2)
34+
swaps.append((x0: num1, x1: num2))
35+
}
36+
37+
private func quicksort ( array: inout [Int], left: Int, right: Int) {
38+
let pivot = right;
39+
var low = left;
40+
var high = right-1;
41+
42+
if(right == low || high < low) {
43+
return
44+
}
45+
for _ in 0...array.count {
46+
if(low <= high) {
47+
if(array[low] < array[pivot]) {
48+
low = low + 1;
49+
continue;
50+
}
51+
if( array[high] > array[pivot]) {
52+
high = high - 1;
53+
continue;
54+
}
55+
swap(array: &array, num1: low, num2: high);
56+
low = low + 1;
57+
high = high - 1;
58+
} else {
59+
swap(array: &array, num1: pivot, num2: low)
60+
break;
61+
}
62+
}
63+
quicksort(array: &array, left: left, right: high)
64+
quicksort(array: &array, left: low + 1, right: right)
65+
66+
}
67+
}

‎SortingAlgorithms/Scenes/AlgorithmDetail/AlgorithmDetailPresenter.swift

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,28 @@ final class AlgorithmDetailPresenter {
1212

1313
private weak var view: AlgorithmDetailView?
1414
private let algorithm: Algorithm
15-
private lazy var datasource = [Int]()
15+
private lazy var dataSource = [Int]()
16+
private(set) var dataSourceBackup = [Int]()
1617
private var swaps = [(x0: Int, x1: Int)]()
1718
private let router: AlgorithmDetailRoutering
1819

1920
init (router: AlgorithmDetailRoutering, algorithm: Algorithm, datasource: [Int]) {
2021
self.router = router
2122
self.algorithm = algorithm
22-
self.datasource = datasource
23+
self.dataSource = datasource
24+
self.dataSourceBackup = datasource
2325
}
2426

2527
func attachView(_ view: AlgorithmDetailView) {
2628
self.view = view
2729

2830
view.setNavigationBarTitle(algorithm.title)
29-
view.updateDataSource(datasource)
30-
swaps = algorithm.generateSwaps(from: datasource)
31+
view.updateDataSource(dataSource, reloadData: false)
32+
generateSwaps()
33+
}
34+
35+
private func generateSwaps() {
36+
swaps = algorithm.generateSwaps(from: dataSource)
3137
}
3238

3339
func viewDidAppear() {
@@ -38,14 +44,27 @@ final class AlgorithmDetailPresenter {
3844
startSwap()
3945
}
4046

41-
private func startSwap() {
47+
func restart() {
48+
dataSource = dataSourceBackup
49+
view?.updateDataSource(dataSource, reloadData: true)
4250

43-
if swaps.count > 0 {
44-
algorithm.swapDataSource(datasource: &datasource, x0: swaps[0].x0, x1: swaps[0].x1)
45-
view?.updateDataSource(datasource)
46-
view?.swapCell(x0: swaps[0].x0, x1: swaps[0].x1)
47-
swaps.removeFirst()
51+
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
52+
guard let self = self else { return }
53+
self.generateSwaps()
54+
self.startSwap()
55+
}
56+
}
57+
58+
private func startSwap() {
59+
guard swaps.count > 0 else {
60+
view?.allSwapsDidEnd()
61+
return
4862
}
63+
64+
algorithm.swapDataSource(datasource: &dataSource, x0: swaps[0].x0, x1: swaps[0].x1)
65+
view?.updateDataSource(dataSource, reloadData: false)
66+
view?.swapCell(x0: swaps[0].x0, x1: swaps[0].x1)
67+
swaps.removeFirst()
4968
}
5069

5170
func closeButtonTriggered() {

‎SortingAlgorithms/Scenes/AlgorithmDetail/AlgorithmDetailProtocol.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@
99
import Foundation
1010

1111
protocol AlgorithmDetailView: AnyObject {
12-
func updateDataSource(_ datasource: [Int])
12+
func updateDataSource(_ datasource: [Int], reloadData: Bool)
1313
func swapCell(x0: Int, x1: Int)
1414
func setNavigationBarTitle(_ text: String)
15+
func allSwapsDidEnd()
1516
}
1617

1718
protocol AlgorithmDetailRoutering: AnyObject {

‎SortingAlgorithms/Scenes/AlgorithmDetail/AlgorithmDetailViewController.swift

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,24 @@ import UIKit
1111

1212
final class AlgorithmDetailViewController: UIViewController {
1313

14+
lazy var closeButton: UIBarButtonItem = {
15+
var rightButton = UIBarButtonItem(
16+
barButtonSystemItem: UIBarButtonItem.SystemItem.stop,
17+
target: self,
18+
action: #selector(closeButtonDidTouchUpInside)
19+
)
20+
return rightButton
21+
}()
22+
23+
lazy var restartButton: UIBarButtonItem = {
24+
let restartButton = UIBarButtonItem(
25+
barButtonSystemItem: .refresh,
26+
target: self,
27+
action: #selector(restartButtonDidTouchUpInside))
28+
restartButton.isEnabled = false
29+
return restartButton
30+
}()
31+
1432
lazy var collectionView: UICollectionView = {
1533
let layout = UICollectionViewFlowLayout()
1634
layout.scrollDirection = .vertical
@@ -60,13 +78,10 @@ final class AlgorithmDetailViewController: UIViewController {
6078
private func setupNavigationBar() {
6179
navigationController?.navigationBar.prefersLargeTitles = false
6280

63-
let rightButton = UIBarButtonItem(
64-
barButtonSystemItem: UIBarButtonItem.SystemItem.stop,
65-
target: self,
66-
action: #selector(closeButtonDidTouchUpInside)
67-
)
68-
69-
self.navigationItem.rightBarButtonItem = rightButton
81+
self.navigationItem.rightBarButtonItems = [
82+
restartButton,
83+
closeButton
84+
]
7085
}
7186

7287
private func setupCollectionView() {setupNavigationBar()
@@ -83,16 +98,29 @@ final class AlgorithmDetailViewController: UIViewController {
8398
@objc private func closeButtonDidTouchUpInside() {
8499
presenter.closeButtonTriggered()
85100
}
101+
102+
@objc private func restartButtonDidTouchUpInside() {
103+
presenter.restart()
104+
restartButton.isEnabled = false
105+
}
86106
}
87107

88108
extension AlgorithmDetailViewController: AlgorithmDetailView {
89109

110+
func allSwapsDidEnd() {
111+
restartButton.isEnabled = true
112+
}
113+
90114
func setNavigationBarTitle(_ text: String) {
91115
navigationItem.title = text
92116
}
93117

94-
func updateDataSource(_ datasource: [Int]) {
118+
func updateDataSource(_ datasource: [Int], reloadData: Bool) {
95119
self.datasource = datasource
120+
121+
if reloadData {
122+
self.collectionView.reloadData()
123+
}
96124
}
97125

98126
func swapCell(x0: Int, x1: Int) {

‎SortingAlgorithms/Scenes/AlgorithmsList/AlgorithmsListPresenter.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ class AlgorithmsListPresenter {
1616
private let dataSource: [Algorithm] = [
1717
BubbleSort(),
1818
InsertionSort(),
19-
SelectionSort()
19+
SelectionSort(),
20+
QuickSort()
2021
]
2122

2223
init (router: AlgorithmsListRoutering) {

‎SortingAlgorithms/Scenes/DataSourceInput/DataSourcePresenter.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,14 @@ final class DataSourcePresenter {
5858
}
5959
}
6060

61+
func addSampleArray() {
62+
array = randomNumbers(10)
63+
view?.clearInputField()
64+
newValue = ""
65+
view?.updateArray("\(array)")
66+
}
67+
68+
private func randomNumbers(_ total: Int) -> [Int] {
69+
return (0..<total).map { _ in .random(in: 1...40) }
70+
}
6171
}

‎SortingAlgorithms/Scenes/DataSourceInput/DataSourceViewController.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,18 @@ final class DataSourceViewController: UIViewController {
6262
return label
6363
}()
6464

65+
private let addSampleButton: UIButton = {
66+
let button = UIButton(type: .system)
67+
button.titleLabel?.font = UIFont(name: "Avenir", size: 20)
68+
button.setTitleColor(#colorLiteral(red: 0, green: 0.9768045545, blue: 0, alpha: 1), for: .normal)
69+
button.setTitle("Sample Array", for: .normal)
70+
button.layer.cornerRadius = 8
71+
button.translatesAutoresizingMaskIntoConstraints = false
72+
button.backgroundColor = #colorLiteral(red: 0.2588235438, green: 0.7568627596, blue: 0.9686274529, alpha: 1).withAlphaComponent(0.3)
73+
74+
return button
75+
}()
76+
6577
let presenter: DataSourcePresenter
6678

6779
init(presenter: DataSourcePresenter) {
@@ -84,6 +96,7 @@ final class DataSourceViewController: UIViewController {
8496
setupAddButton()
8597
setupRemoveButton()
8698
setupArrayLabel()
99+
setupAddSampleButton()
87100

88101
presenter.attachView(self)
89102
}
@@ -150,6 +163,19 @@ final class DataSourceViewController: UIViewController {
150163
removeButton.addTarget(self, action: #selector(removeButtonTouchUpInside), for: .touchUpInside)
151164
}
152165

166+
private func setupAddSampleButton() {
167+
view.addSubview(addSampleButton)
168+
169+
NSLayoutConstraint.activate([
170+
addSampleButton.topAnchor.constraint(equalTo: arrayLabel.bottomAnchor, constant: 20.0),
171+
addSampleButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
172+
addSampleButton.widthAnchor.constraint(equalToConstant: 140.0),
173+
addSampleButton.heightAnchor.constraint(equalToConstant: 40.0)
174+
])
175+
176+
addSampleButton.addTarget(self, action: #selector(addSampleArrayTouchUpInside), for: .touchUpInside)
177+
}
178+
153179
@objc private func runTouchUpInside() {
154180
presenter.runTriggered()
155181
}
@@ -161,6 +187,10 @@ final class DataSourceViewController: UIViewController {
161187
@objc private func removeButtonTouchUpInside() {
162188
presenter.removeButtonTriggered()
163189
}
190+
191+
@objc private func addSampleArrayTouchUpInside() {
192+
presenter.addSampleArray()
193+
}
164194

165195
}
166196

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"images" : [
3+
{
4+
"idiom" : "universal",
5+
"filename" : "quick_sorting.png",
6+
"scale" : "1x"
7+
},
8+
{
9+
"idiom" : "universal",
10+
"filename" : "quick_sorting@2x.png",
11+
"scale" : "2x"
12+
},
13+
{
14+
"idiom" : "universal",
15+
"filename" : "quick_sorting@3x.png",
16+
"scale" : "3x"
17+
}
18+
],
19+
"info" : {
20+
"version" : 1,
21+
"author" : "xcode"
22+
}
23+
}
Loading

0 commit comments

Comments
 (0)
Failed to load comments.