Skip to content

Commit

Permalink
Merge branch 'master' into graphs
Browse files Browse the repository at this point in the history
  • Loading branch information
carloshmartins authored May 14, 2024
2 parents b2cf450 + c864c82 commit 5ff494b
Show file tree
Hide file tree
Showing 11 changed files with 572 additions and 0 deletions.
15 changes: 15 additions & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,20 @@
* [Boardtests](https://github.com/TheAlgorithms/Swift/blob/master/algorithms/AI/minimax/Sources/Tests/Tests/BoardTests.swift)
* [Minimaxtests](https://github.com/TheAlgorithms/Swift/blob/master/algorithms/AI/minimax/Sources/Tests/Tests/MinimaxTests.swift)
* [Playertests](https://github.com/TheAlgorithms/Swift/blob/master/algorithms/AI/minimax/Sources/Tests/Tests/PlayerTests.swift)
* Conversion
* [Binary-To-Decimal](https://github.com/TheAlgorithms/Swift/blob/master/algorithms/conversion/binary-to-decimal.swift)
* [Decimal-To-Binary](https://github.com/TheAlgorithms/Swift/blob/master/algorithms/conversion/decimal-to-binary.swift)
* Palindrome
* [Palindrome Indices](https://github.com/TheAlgorithms/Swift/blob/master/algorithms/palindrome/palindrome_indices.swift)
* [Palindrome Recursion](https://github.com/TheAlgorithms/Swift/blob/master/algorithms/palindrome/palindrome_recursion.swift)
* [Palindrome Reversed](https://github.com/TheAlgorithms/Swift/blob/master/algorithms/palindrome/palindrome_reversed.swift)
* Parsing
* Shunting Yard
* [Shunting Yard](https://github.com/TheAlgorithms/Swift/blob/master/algorithms/parsing/shunting_yard/shunting_yard.swift)

## Data Structures
* Doubly Linked List
* [Doublylinkedlist](https://github.com/TheAlgorithms/Swift/blob/master/data_structures/doubly_linked_list/DoublyLinkedList.swift)
* Heap
* [Heap](https://github.com/TheAlgorithms/Swift/blob/master/data_structures/heap/heap.swift)
* Linked List
Expand All @@ -47,6 +56,10 @@

## Graph
* [Graph](https://github.com/TheAlgorithms/Swift/blob/master/graph/Graph.swift)
* Bfs
* [Bfs](https://github.com/TheAlgorithms/Swift/blob/master/graph/BFS/BFS.swift)
* Dfs
* [Dfs](https://github.com/TheAlgorithms/Swift/blob/master/graph/DFS/DFS.swift)
* Spanning Tree
* [Kruskal](https://github.com/TheAlgorithms/Swift/blob/master/graph/spanning_tree/kruskal.swift)

Expand All @@ -59,8 +72,10 @@

## Sorts
* [Bubblesort](https://github.com/TheAlgorithms/Swift/blob/master/sorts/BubbleSort.swift)
* [Cocktailsort](https://github.com/TheAlgorithms/Swift/blob/master/sorts/CocktailSort.swift)
* [Insertionsort](https://github.com/TheAlgorithms/Swift/blob/master/sorts/InsertionSort.swift)
* [Mergesort](https://github.com/TheAlgorithms/Swift/blob/master/sorts/MergeSort.swift)
* [Pancakesort](https://github.com/TheAlgorithms/Swift/blob/master/sorts/PancakeSort.swift)
* [Quicksort](https://github.com/TheAlgorithms/Swift/blob/master/sorts/QuickSort.swift)
* [Selectionsort](https://github.com/TheAlgorithms/Swift/blob/master/sorts/SelectionSort.swift)

Expand Down
23 changes: 23 additions & 0 deletions algorithms/conversion/binary-to-decimal.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Foundation

/// This function accepts a binary number as String and converts it to decimal as Int.
/// If it's not valid binary number (a.k.a not made only from digits), it returns nil.
public func convertBinaryToDecimal(binary: String) -> Int? {
if let _ = Int(binary) {
var decimal = 0

let digits = binary.map { Int(String($0))! }.reversed()
print(digits)
var power = 1

for digit in digits {
decimal += digit * power

power *= 2
}

return decimal
}

return nil
}
12 changes: 12 additions & 0 deletions algorithms/conversion/decimal-to-binary.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/// This function accepts a non-negative number and returns its binary form as String.
public func convertDecimalToBinary(decimal: Int) -> String {
var binary = ""
var decimal = decimal

while decimal != 0 {
binary.insert(decimal % 2 == 0 ? "0" : "1", at: binary.startIndex)
decimal /= 2
}

return binary
}
32 changes: 32 additions & 0 deletions algorithms/palindrome/palindrome_indices.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// A palindrome is a string that reads the same forwards and backwards.
//
// Examples: "level", "radar", "madam", "A man, a plan, a canal: Panama".

extension String {

/// Iteratively comparing characters from the beginning and end of the string. Only include letters and numbers.
/// - Complexity: O(n), without allocating new space.
func isPalindrome() -> Bool {
var leftIndex = startIndex
var rightIndex = index(before: endIndex)

while leftIndex < rightIndex {
guard self[leftIndex].isLetter || self[leftIndex].isNumber else {
leftIndex = index(after: leftIndex)
continue
}
guard self[rightIndex].isLetter || self[rightIndex].isNumber else {
rightIndex = index(before: rightIndex)
continue
}
guard self[leftIndex].lowercased() == self[rightIndex].lowercased() else {
return false
}

leftIndex = index(after: leftIndex)
rightIndex = index(before: rightIndex)
}

return true
}
}
44 changes: 44 additions & 0 deletions algorithms/palindrome/palindrome_recursion.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// A palindrome is a string that reads the same forwards and backwards.
//
// Examples: "level", "radar", "madam", "A man, a plan, a canal: Panama".

extension String {

/// Recursively comparing characters from the beginning and end of the string. Only include letters and numbers.
/// - Complexity: O(n), without allocating new space.
func isPalindrome() -> Bool {
isPalindromeRecursion(
leftIndex: startIndex,
rightIndex: index(before: endIndex)
)
}

private func isPalindromeRecursion(
leftIndex: String.Index,
rightIndex: String.Index
) -> Bool {
guard leftIndex < rightIndex else {
return true
}
guard self[leftIndex].isLetter || self[leftIndex].isNumber else {
return isPalindromeRecursion(
leftIndex: index(after: leftIndex),
rightIndex: rightIndex
)
}
guard self[rightIndex].isLetter || self[rightIndex].isNumber else {
return isPalindromeRecursion(
leftIndex: leftIndex,
rightIndex: index(before: rightIndex)
)
}
guard self[leftIndex].lowercased() == self[rightIndex].lowercased() else {
return false
}

return isPalindromeRecursion(
leftIndex: index(after: leftIndex),
rightIndex: index(before: rightIndex)
)
}
}
13 changes: 13 additions & 0 deletions algorithms/palindrome/palindrome_reversed.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// A palindrome is a string that reads the same forwards and backwards.
//
// Examples: "level", "radar", "madam", "A man, a plan, a canal: Panama".

extension String {

/// Using the `reverse()` method to reverse the string and comparing it with the original. Only include letters and numbers.
/// - Complexity: O(n), with allocating O(n) space.
func isPalindrome() -> Bool {
let input = lowercased().filter { $0.isLetter || $0.isNumber }
return input == String(input.reversed())
}
}
194 changes: 194 additions & 0 deletions data_structures/doubly_linked_list/DoublyLinkedList.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
import Foundation

public class Node<Value> {
public var value: Value?
public var next: Node?
public var prev: Node?

public init(value: Value? = nil, next: Node<Value>? = nil, prev: Node<Value>? = nil) {
self.value = value
self.next = next
self.prev = prev
}
}

extension Node: CustomStringConvertible {
public var description: String {
guard let next: Node<Value> = self.next else {
return "\(String(describing: value))"
}
return "\(String(describing: value)) <-> \(String(describing: next)) "
}
}

public struct DoublyLinkedList<Value> {

public var head: Node<Value>?
public var tail: Node<Value>?
public var count: Int = 0

public var isEmpty: Bool {
return head == nil
}

public mutating func push(_ value: Value) {
let new: Node<Value> = Node(value: value, next: head)
if head != nil { head!.prev = new }
head = new
if tail == nil { tail = head }
count += 1
}

public mutating func append(_ value: Value) {
guard !isEmpty else {
push(value)
return
}
tail!.next = Node(value: value, prev: tail)
tail = tail!.next
count += 1
}

@discardableResult
public mutating func insert(_ value: Value,
after node: Node<Value>) -> Node<Value> {
guard tail !== node else {
append(value)
return tail!
}
var new: Node<Value> = Node(value: value, next: node.next, prev: node)
node.next?.prev = new
node.next = new
count += 1
return node.next!
}

@discardableResult
public mutating func insert(_ value: Value,
before node: Node<Value>) -> Node<Value> {
guard head !== node else {
push(value)
return head!
}
var new: Node<Value> = Node(value: value, next: node, prev: node.prev)
node.prev?.next = new
node.prev = new
count += 1
return node.prev!
}

public func node(at index: Int) -> Node<Value>? {
guard index > -1 || index < count else { return nil }

let startFromTail: Bool = index > count / 2
var currentNode: Node<Value>? = startFromTail ? tail : head
var currentIndex: Int = startFromTail ? count - 1 : 0
var change: Int = startFromTail ? -1 : 1

while currentNode != nil {
if currentIndex == index { break }
currentNode = startFromTail ? currentNode!.prev : currentNode!.next
currentIndex += change
}

return currentNode
}

@discardableResult
public mutating func pop() -> Value? {
defer {
head = head?.next
count -= 1
if isEmpty {
tail = nil
} else {
head!.prev = nil
}
}
return head?.value
}

@discardableResult
public mutating func removeLast() -> Value? {
defer {
tail = tail?.prev
count -= 1
if isEmpty {
head = nil
} else {
tail!.next = nil
}
}
return tail?.value
}

@discardableResult
public mutating func remove(after node: Node<Value>) -> Value? {
defer {
if node.next != nil {
count -= 1
}
if node.next === tail {
tail = node
}
if let next2node: Node<Value> = node.next?.next {
next2node.prev = node
}
node.next = node.next?.next
}
return node.next?.value
}

@discardableResult
public mutating func remove(before node: Node<Value>) -> Value? {
defer {
if node.prev != nil {
count -= 1
}
if node.prev === head {
head = node
}
if let prev2node: Node<Value> = node.prev?.prev {
prev2node.next = node
}
node.prev = node.prev?.prev
}
return node.prev?.value
}
}

extension DoublyLinkedList: CustomStringConvertible {
public var description: String {
guard let head: Node<Value> = self.head else {
return "Empty list"
}
return String(describing: head)
}
}

// Here are testing scenarios to run in a Swift playground

/*
var list = DoublyLinkedList<Int>()
list.push(4)
list.push(2)
list.push(1)
list.append(6)
var n = list.node(at: 2)
list.insert(5, after: n!)
list.insert(3, before: n!)
print(list)
print(list.pop()!)
print(list.removeLast()!)
print(list.remove(after: n!)!)
print(list.remove(before: n!)!)
print(list.count)
*/
Loading

0 comments on commit 5ff494b

Please sign in to comment.