I am trying to create a recursive Swift implementation for the solution of the classic puzzle: "How can we distribute n queens on a chess grid of n × n so that no queen can threaten another".
With existing code I encountered the following problems:
Code does not produce all the solutions for n<=8
Code does not product ANY solution for n>=9
Can't seem to compare solutions for n=8 (8x8) and larger because I compute the hash for each Solution class (board) by shifting bits which represent existence of queen or empty tile:
public override var hash: Int {
var hash = 0
for i in 0...self.board.count-1 {
for j in 0...self.board.count-1 {
if self.board[i][j].state == .Queen {
hash |= 1
hash <<= 1
} else {
hash <<= 1
}
}
}
return hash
}
when board is >8x8 value gets corrupted as it is larger than 64 bits (swift Int is Int64). What's a good solution for that?
My current code:
import UIKit
public typealias Board = Array<Array<Cell>>
#objc protocol QueenPlacementDelegate : class {
func solutionsFound(numOfSolutions : Int)
}
class QueenPlacement: NSObject {
var boardView : TTTBoardView?
var boardSize : Int = 0
var solutions : Set<Solution>?
weak var delegate : QueenPlacementDelegate?
private var startCondX : Int = 0
private var startCondY : Int = 0
func start() {
if boardSize == 0 {
print("Board size was not initialized")
return
}
self.solutions = Set<Solution>()
var done = false
self.startCondX = 0; self.startCondY = 0;
while (!done) {
let solution = Solution(boardSize: self.boardSize)
let board = solution.board
self.placeQueen(startCondX, yLoc: startCondY, board: board)
let solutionBoard = self.findSolutionForBoard(board)
if self.numOfQueensOnBoard(solutionBoard) == self.boardSize {
print("solution found")
solution.board = solutionBoard
self.solutions!.insert(solution)
}
done = self.advanceStartConditionsAndCheckIfDone()
if (done) {
if self.solutions!.count > 0 {
self.delegate!.solutionsFound(self.solutions!.count)
}
}
}
}
func advanceStartConditionsAndCheckIfDone() -> Bool {
startCondX++
if startCondX >= self.boardSize {
startCondX = 0
startCondY++
if startCondY >= self.boardSize {
return true
}
}
return false
}
func placeQueen(xLoc : Int, yLoc : Int, board : Board) {
board[xLoc][yLoc].state = .Queen
}
func findSolutionForBoard(board : Board) -> Board
{
let queensPlaced = self.numOfQueensOnBoard(board)
if queensPlaced == self.boardSize {
return board
}
else
{
for i in 0...self.boardSize-1 {
for j in 0...self.boardSize-1 {
if self.canPlaceQueen(xLoc: i, yLoc: j, board: board) {
self.placeQueen(i, yLoc: j, board: board)
}
}
}
let newQueensPlaced = self.numOfQueensOnBoard(board)
// recursion exit conditions: could not place any new queen
if newQueensPlaced > queensPlaced {
self.findSolutionForBoard(board)
} else {
return board
}
}
return board
}
func numOfQueensOnBoard(board : Board) -> Int {
var queensPlaced = 0
for i in 0...self.boardSize-1 {
for j in 0...self.boardSize-1 {
if board[i][j].state == .Queen {
queensPlaced++
}
}
}
return queensPlaced
}
func canPlaceQueen(xLoc xLoc : Int, yLoc : Int, board: Board) -> Bool {
for i in 0...self.boardSize-1 {
if board[i][yLoc].state == .Queen {
return false;
}
if board[xLoc][i].state == .Queen {
return false;
}
}
var x : Int
var y : Int
x = xLoc; y = yLoc;
while ++x < self.boardSize && ++y < self.boardSize {
if board[x][y].state == .Queen {
return false
}
}
x = xLoc; y = yLoc;
while --x >= 0 && ++y < self.boardSize {
if board[x][y].state == .Queen {
return false
}
}
x = xLoc; y = yLoc;
while ++x < self.boardSize && --y >= 0 {
if board[x][y].state == .Queen {
return false
}
}
x = xLoc; y = yLoc;
while --x >= 0 && --y >= 0 {
if board[x][y].state == .Queen {
return false
}
}
return true
}
// singleton!
static let sharedInstance = QueenPlacement()
private override init() {}
}
What is wrong here?
P.S.
for easier reading - full code repo can be found here
It's not an answer in a way that I don't know what is the problem with your version, but here is another one (looks working as I tested it), a little bit simplier (based on Scala By Example - The N-Queens Problem).
func queens(n: Int) -> [[Int]] {
guard n > 3 else {
return [[Int]]()
}
func placeQueens(k: Int) -> [[Int]] {
guard k > 0 else {
return [[-1]] //stupid hack to let the app go to the for-loop in the * marked place
}
var res = [[Int]]()
for var q in placeQueens(k - 1) { //* marked place
if let first = q.first where first == -1 { //this is for removing the hacky -1
q.removeAll()
}
for column in 1...n {
if isSafe(column, queens: q) {
var solution = q
solution.append(column)
res.append(solution)
}
}
}
return res
}
return placeQueens(n)
}
func isSafe(column: Int, queens: [Int]) -> Bool {
for (index, q) in queens.enumerate() {
let dy = (index + 1) - (queens.count + 1)
let dx = q - column
let isDiagonal = dy * dy == dx * dx
if q == column || isDiagonal {
return false
}
}
return true
}
And if you want to draw the solutions out:
func drawTable(table: [Int]) -> String {
var res = ""
table.forEach {
for column in 1...table.count {
if $0 == column {
res += "X "
} else {
res += ". "
}
}
res += "\n"
}
return res
}
And
queens(4).forEach {
print(drawTable($0))
}
Computing the 73712 solutions of n = 13 took some minutes, above that you would probably run out of memory this way.
Related
I have been using the Chatto framework for working in a chat application. Everything works fine. Now I want to delete a chat message from DataSource which is SlidingDataSource class. The indexing of the array is being handled with some properties like windowOffset itemsOffset windowCount along with the array's count. If anyone has used delete operation in Chatto, Please explain the properties or provide a simple function to delete will be helpful.
Thank you. I am attaching the data source code here..
import Foundation
import Chatto
public enum InsertPosition {
case top
case bottom
}
public class SlidingDataSource<Element> {
private var pageSize: Int
private var windowOffset: Int
private var windowCount: Int
private var itemGenerator: (() -> Element)?
private var items = [Element]()
private var itemsOffset: Int
public var itemsInWindow: [Element] {
let offset = self.windowOffset - self.itemsOffset
return Array(items[offset..<offset+self.windowCount])
}
public init(count: Int, pageSize: Int, itemGenerator: (() -> Element)?) {
self.windowOffset = count
self.itemsOffset = count
self.windowCount = 0
self.pageSize = pageSize
self.itemGenerator = itemGenerator
self.generateItems(min(pageSize, count), position: .top)
}
public convenience init(items: [Element], pageSize: Int) {
var iterator = items.makeIterator()
self.init(count: items.count, pageSize: pageSize) { iterator.next()! }
}
private func generateItems(_ count: Int, position: InsertPosition) {
// swiftlint:disable:next empty_count
guard count > 0 else { return }
guard let itemGenerator = self.itemGenerator else {
fatalError("Can't create messages without a generator")
}
for _ in 0..<count {
self.insertItem(itemGenerator(), position: .top)
}
}
public func insertItem(_ item: Element, position: InsertPosition) {
if position == .top {
self.items.insert(item, at: 0)
let shouldExpandWindow = self.itemsOffset == self.windowOffset
self.itemsOffset -= 1
if shouldExpandWindow {
self.windowOffset -= 1
self.windowCount += 1
}
} else {
let shouldExpandWindow = self.itemsOffset + self.items.count == self.windowOffset + self.windowCount
if shouldExpandWindow {
self.windowCount += 1
}
self.items.append(item)
}
}
public func hasPrevious() -> Bool {
return self.windowOffset > 0
}
public func hasMore() -> Bool {
return self.windowOffset + self.windowCount < self.itemsOffset + self.items.count
}
public func loadPrevious() {
let previousWindowOffset = self.windowOffset
let previousWindowCount = self.windowCount
let nextWindowOffset = max(0, self.windowOffset - self.pageSize)
let messagesNeeded = self.itemsOffset - nextWindowOffset
if messagesNeeded > 0 {
self.generateItems(messagesNeeded, position: .top)
}
let newItemsCount = previousWindowOffset - nextWindowOffset
self.windowOffset = nextWindowOffset
self.windowCount = previousWindowCount + newItemsCount
}
public func loadNext() {
guard !self.items.isEmpty else { return }
let itemCountAfterWindow = self.itemsOffset + self.items.count - self.windowOffset - self.windowCount
self.windowCount += min(self.pageSize, itemCountAfterWindow)
}
#discardableResult
public func adjustWindow(focusPosition: Double, maxWindowSize: Int) -> Bool {
assert(0 <= focusPosition && focusPosition <= 1, "")
guard 0 <= focusPosition && focusPosition <= 1 else {
assert(false, "focus should be in the [0, 1] interval")
return false
}
let sizeDiff = self.windowCount - maxWindowSize
guard sizeDiff > 0 else { return false }
self.windowOffset += Int(focusPosition * Double(sizeDiff))
self.windowCount = maxWindowSize
return true
}
#discardableResult
func replaceItem(withNewItem item: Element, where predicate: (Element) -> Bool) -> Bool {
guard let index = self.items.firstIndex(where: predicate) else { return false }
self.items[index] = item
return true
}
func contains(item: Element, where predicate: (Element) -> Bool ) -> Bool {
guard let _ = self.items.firstIndex(where: predicate) else { return false }
return true
}
//FIXME: Add delete method here, don't know the use off itemOffset, windowOffset, windowCount
// func delete(item: Element, where predicate: (Element) -> Bool ) {
// self.items.removeAll(where: predicate)
// }
}
I have raised a question in their Github repo. Here is the solution they answered.
when delete or add a new element in data source you need to -1 or +1 to offset. If offset is 0 - do nothing.
Originial answer link
I am developing an app (in XCode Version 11.2 and Swift 4.2) in which I fill in a LinkedList and after working with it, removing the elements that compose it produces the Thread 1 error: EXC_BAD_ACCESS (code = 2, address = 0x16d0f3ff0). The error occurs even without working with the items in the list, simply by adding them and trying to eliminate them the error already occurs. The tests I am doing with an iPhone with IOS version 11.4.1
The implementation of the LinkedList is as follows:
import Foundation
public class Node<T> {
var value: T
var next: Node<T>?
weak var previous: Node<T>?
init(value: T) {
self.value = value
} // init
} // Node
public class LinkedList<T> {
private var head: Node<T>?
private var tail: Node<T>?
public private(set) var count: Int = 0
public init() { } // init
public var isEmpty: Bool {
return self.head == nil
} // isEmpty
public var first: Node<T>? {
return self.head
} // first
public var last: Node<T>? {
return self.tail
} // last
public func nodeAt(index: Int) -> Node<T>? {
if index >= 0 {
var node = self.head
var i = index
while node != nil {
if i == 0 {
return node
} // if
i -= 1
node = node!.next
} // while
} // if
return nil
} // nodeAt
public func removeAll() {
self.head = nil
self.tail = nil
self.count = 0
} // removeAll
public func remove(node: Node<T>?) -> String {
if isEmpty {
return String("ERROR: Empty list, nothing to remove.")
} // if
guard node != nil else {
return String("ERROR: Invalid node, nothing to remove.")
} // guard
let prev = node?.previous
let next = node?.next
if next != nil && prev == nil {
self.head = next
next?.previous = nil
} else if next != nil && prev != nil {
prev?.next = next
next?.previous = prev
} else if next == nil && prev != nil {
self.tail = prev
prev?.next = nil
} // if
node?.previous = nil
node?.next = nil
self.count -= 1
return String("Successfully removed node: \(node!.value)")
} // remove
func enqueue(value: T) {
let newNode = Node(value: value)
if let tailNode = self.tail {
newNode.previous = tailNode
tailNode.next = newNode
} else {
self.head = newNode
} // else
self.tail = newNode
self.count += 1
}
func enqueue_first(value: HexRecord) {
let newNode = Node(value: value)
if let headNode = self.head {
newNode.next = headNode
headNode.previous = newNode
}
self.head = newNode
self.count += 1
}
func dequeue() -> T? {
let element = self.head?.value
self.head = self.head?.next
self.count -= 1
return element
}
} // LinkedList
The nodes of the same are of the HexRecord type:
public class HexRecord
{
private var length: Int = 0
private var address: Int64 = 0
private var type: Int32 = 0
private var data = [UInt8] ()
private var checksum: UInt8 = 0
init()
{
}
public func getAddress() -> Int64 {
return address;
}
public func getType() -> Int32 {
return type;
}
public func getData() -> [UInt8] {
return data;
}
public func getLength() -> Int {
return length;
}
public func getChecksum() -> UInt8 {
return checksum;
}
public func setAddress(address: Int64) {
self.address = address;
}
public func setData(data: [UInt8]) {
self.data = data;
}
public func setLength(length: Int) {
self.length = length;
}
public func setType(type: Int32) {
self.type = type;
}
public func setChecksum(checksum: UInt8) {
self.checksum = checksum;
}
}
It is used as follows:
func tratar_registros() {
var records = LinkedList<HexRecord>();
....
let data_line: HexRecord? = try parseRecord(line: line) // parseRecord convert String to HexRecord
if (data_line != nil)
{
records.enqueue(value: data_line!)
}
....
records.removeAll(); //Thread 1: EXC_BAD_ACCESS (code=2, address=0x16d0f3ff0)
} // Thread 1: EXC_BAD_ACCESS (code=2, address=0x16d0f3ff0) if there is no line records.removeAll();
With the debugger I see that the error occurs when assigning the value nil to self.head. Just before self.head has correct values, it becomes nil and the error is skipped before reaching the next instruction (within the removeAll function)
In the Debug Navigator, in the stackTrace the last 2 functions where the error is seen:
libobjc.A.dylib`_object_remove_assocations:
0x180d11eec <+0>: sub sp, sp, #0x70 ; =0x70
-> 0x180d11ef0 <+4>: stp x26, x25, [sp, #0x20] //Thread 1 error: EXC_BAD_ACCESS (code = 2, address = 0x16d0f3ff0)
0x180d11ef4 <+8>: stp x24, x23, [sp, #0x30]
libswiftCore.dylib`_swift_release_:
0x104e18d1c <+180>: bl 0x104e1a37c ; bool swift::RefCounts<swift::SideTableRefCountBits>::doDecrement<(swift::PerformDeinit)1>(unsigned int)
-> 0x104e18d20 <+184>: ldp x29, x30, [sp], #0x10. //Thread 1 error: EXC_BAD_ACCESS (code = 2, address = 0x16d0f3ff0)
0x104e18d24 <+188>: ret
Does someone have idea how to resolve it?
Thanks!
In my case, this error occurred when when I created a circular reference.
I created a Column object, and in the column initializer it counted out of how many columns were to be created. In order to count that list, that getter initialized an array of Columns.
It was solved by changing the removeAll method of the LinkedList, for the following:
public func removeAll() {
while head != nil {
removeTail()
}
}
public func removeTail() {
guard let tail = tail else {return}
if let prev = tail.previous {
prev.next = nil
self.tail = prev
} else {
self.head = nil
self.tail = nil
}
count -= 1
if count < 0 { count = 0}
}
I am trying to write this in swift as I could not find any solution written in swift but seem to have hit a roadblock with this implementation.
On the pop and push function, I am not sure if Character is the right return/argument.
class BalancedParam {
struct stack {
var top = -1
var items = [Character]()
mutating func push(_ x: Character) {
items.append(x)
if top == 99 {
print("Stack full")
} else {
top += 1
items[top] = x
}
}
mutating func pop() -> Character {
if top == -1 {
print("Underflow error")
return "0"
} else {
let element = items[top]
top -= 1
return element
}
}
mutating func isEmpty() -> Bool {
return (top == -1) ? true : false
}
}
static func isMatchingPair(_ character1: Character, _ character2: Character) -> Bool {
if character1 == "(" && character2 == ")" {
return true
} else if character1 == "{" && character2 == "}" {
return true
} else if character1 == "[" && character2 == "]" {
return true
} else {
return false
}
}
static func areParenthesisBalanced(_ exp: [Character]) -> Bool {
// Declare an empty character stack
var st = stack()
for i in 0..<exp.count {
if exp[i] == "{" || exp[i] == "(" || exp[i] == "[" {
st.push(exp[i])
}
if exp[i] == "}" || exp[i] == ")" || exp[i] == "]" {
if st.isEmpty() {
return false
} else if !isMatchingPair(st.pop(), exp[i] ) {
return false
}
}
}
if st.isEmpty() {
return true //balanced
} else {
//not balanced
return false
}
}
}
let exp: [Character] = ["{", "(", ")", "}", "[", "]"]
if BalancedParam.areParenthesisBalanced(exp) {
print("Balanced ")
} else {
print("Not Balanced ")
}
I will appreciate any help in understanding what I am doing wrong. Thanks
You can not assign to an empty array, i.e items[top] = x, you can only use this syntax if the array is of size top+1 or larger
So this is not ok
var arr = [Int]()
arr[0] = 1
but this is
var arr = [Int]()
arr.append(0)
arr[0] = 1
Another option since you have a cap on your array size is to init an array of that size and then continue to use the original syntax
var arr = Array(repeating: 0, count: 99)
arr[0] = 1
I am trying to redevelop the Colony class I wrote for Conway's Game of Life with Sets instead of arrays but am having trouble doing so. Here's what I've got so far:
P.S. I am assuming a fixed Colony size of 20x20.
import Foundation
struct Array2DB {
var values: [Int]
var rows: Int
var cols: Int
init(rows: Int, cols: Int){
self.rows = rows
self.cols = cols
values = [Int](repeating: 0, count: (rows + 2) * (cols + 2) )
}
//allows uasge of the syntax [row, col] for get/set access
subscript(row:Int, col: Int) -> Int {
get {
return values[getIndex(row, col)]
}
set(val) {
values[getIndex(row, col)] = val
}
}
//converts 2D indices to index in data (terminates if out of bounds)
func getIndex(_ row: Int, _ col: Int) -> Int {
assert((row >= -1) && (row <= rows), "row \(row) is out of bounds")
assert((col >= -1) && (col <= cols), "col \(col) is out of bounds")
return (row + 1) * cols + col + 1
}
var description: String {
var desc = "Matrix:\n"
for row in 0 ..< rows {
for col in 0 ..< cols {
desc += " \(values[getIndex(row, col)]) "
}
desc += "\n"
}
return desc
}
}
class Colony: CustomStringConvertible {
let colony: Set = Array2DB[rows, cols, values]
func setCellAlive(xCoor: Int, yCoor: Int) {
colony[xCoor, yCoor] = 1
}
func setCellDead(xCoor:Int, yCoor: Int) {
colony[xCoor, yCoor] = 0
}
func resetColony() {
for i in 0..<colony.rows {
for e in 0..<colony.cols {
colony[i, e] = 0
}
}
}
var description: String {
var desc = ""
for i in 0..<colony.rows {
for e in 0..<colony.cols {
if colony[i, e] == 1 {
desc += "*"
} else {
desc += "-"
}
}
desc += "\n"
}
return desc
}
func isCellALive( xCoor: Int, yCoor: Int) -> Bool{
return colony[xCoor, yCoor] == 1
}
func evolve() {
var colonyUpdate: Array2DB = colony
for i in 0..<colony.rows {
for e in 0..<colony.cols {
let cGen = rules(xCoor: i, yCoor: e)
if ((cGen < 2) || (cGen > 3)) {
colonyUpdate[i, e] = 0
} else if cGen == 3 {
colonyUpdate[i, e] = 1
} else {
if colony[i, e] == 1 {
colonyUpdate[i, e] = 1
} else {
colonyUpdate[i, e] = 0
}
}
}
}
colony = colonyUpdate
}
}
I'm sure that I've implemented it wrong, but how would I turn the arrays to sets? I'm really confused and would appreciate any guidance or feedbac
Your data type Array2DB is not an Array. It is a Struct that contains an array. You can't assign an Array2DB to a variable that you've declared to be of type Set. It won't work.
You also can't use a Set as the storage for Conway's game of life. The Swift Set data type is an unordered collection. It is unsuitable to serve as the storage for the data in the game of life. You want an array, period.
A very little help for you to show an example of using Set in Game of Life.
struct Cell: Hashable {
var x: Int
var y: Int
}
class Colony: CustomStringConvertible {
var aliveCells: Set = Set<Cell>()
let numberOfRows: Int
let numberOfColumns: Int
init(colonySize: Int) {
self.numberOfRows = colonySize
self.numberOfColumns = colonySize
}
func setCellAlive(xCoor: Int, yCoor: Int) {
aliveCells.insert(Cell(x: xCoor, y: yCoor))
}
func setCellDead(xCoor:Int, yCoor: Int) {
aliveCells.remove(Cell(x: xCoor, y: yCoor))
}
func resetColony() {
aliveCells.removeAll(keepingCapacity: true)
}
var description: String {
var desc = ""
for i in 0..<numberOfRows {
for e in 0..<numberOfColumns {
if aliveCells.contains(Cell(x: e, y: i)) { //Usually `x` represents column, and `y` for row
desc += "*"
} else {
desc += "-"
}
}
desc += "\n"
}
return desc
}
//Implement other methods you need
//...
}
As already noted, Set is not a good data type for Game of Life. But you can implement it using Set. Good luck.
I am wondering how to input UInt8 divided into 3bit and 5bit.
Var val: UInt8 = 0
Val.bit3 = 0x06 // 110
Val.bit5 = 0x11 // 10000
i want result:
11010000 or 10000110 (3bit / 5bit or 5bit / 3bit)
extension UInt8 {
var bit3 : UInt8 {
get {
??
}
set(newValue) {
??
}
}
var bit5 : UInt8 {
get {
??
}
set(newValue) {
??
}
}
}
How do I do bitwise operations to get the result above?
... Thank you
You can do something like that
extension UInt8 {
var bit3 : UInt8 {
get {
return (self & 0b1110_0000) >> 5
}
set(newValue) {
self &= 0b0001_1111
self |= ((newValue << 5) & 0b1110_0000)
}
}
var bit5 : UInt8 {
get {
return self & 0b0001_1111
}
set(newValue) {
self &= 0b1110_0000
self |= (newValue & 0b0001_1111)
}
}
}
bit3 here is "top" and bit5 is "bottom".
EDIT: Forgot to clean bits before setting