Swift编程

swift解决双蛋问题

2020-03-15  本文已影响0人  iceger

双蛋问题:

有t层楼,n个鸡蛋,鸡蛋从某层楼以上掉下肯定会摔碎,从该层楼以下掉下肯定不会摔碎。现在求最少扔几次能够找到临界楼层。

用swift写了个commandline程序,代码如下:

//  main.swift
//  DoubleEggs
//
//  Created by 闪光灯 on 2020/3/15.
//  Copyright © 2020 闪光灯. All rights reserved.
//

import Foundation


struct DoubleEggs{
    var tFloors :Int//楼层数
    var nEggs:Int//鸡蛋数
    //二维数组存储计算结果
    var mResult:Array2D<Int> {
        var result = Array2D(columns: tFloors + 1, rows: nEggs + 1, initialValue: 0)
        //先存储第一行数据
        for i in 1...tFloors{
            result[i,1] = i
        }
        for i in 1...nEggs{
            result[1,i] = 1
        }
        //递归算法计算其余结果
        for floors in 2...tFloors{
            for eggs in  2...nEggs{
                var minn = 100
                for k in 1...floors{
                    //k为选择从第k层扔鸡蛋,result[t,n] = min(M1(t,n)..Mk(t,n)..Mt(t,n)),而Mk(t,n)= max(M(k-1,n-1),M(t-k,n))+1
                    //k从1到t逐一比较Mk,用minn存储最小值
                  minn = min(minn,max(result[k - 1,eggs - 1], result[floors - k,eggs]) + 1)
                }
                result[floors,eggs] = minn
            }
        }
        return result
    }
    //打印表格
    func printTable(){
        for i in 1...tFloors{
            print("\(i)floor\t\t",terminator:"")
        for j in 1...nEggs{
            print("\(mResult[i,j])\t" ,terminator:"")
        }
            print("\n",terminator:"")
        }
    }
    //只打印单个结果
    func printResult(){
        print("计算中...")
        print("\(tFloors)层楼\(nEggs)个鸡蛋最少需扔\(mResult[tFloors,nEggs])次")
    }
    
}

//二维数组方法,可以用[a,b]下标读取和写入数据
public struct Array2D<T> {
  public let columns: Int
  public let rows: Int
  fileprivate var array: [T]
  
  public init(columns: Int, rows: Int, initialValue: T) {
    self.columns = columns
    self.rows = rows
    array = .init(repeating: initialValue, count: rows*columns)
  }
  
  public subscript(column: Int, row: Int) -> T {
    get {
      precondition(column < columns, "Column \(column) Index is out of range. Array<T>(columns: \(columns), rows:\(rows))")
      precondition(row < rows, "Row \(row) Index is out of range. Array<T>(columns: \(columns), rows:\(rows))")
      return array[row*columns + column]
    }
    set {
      precondition(column < columns, "Column \(column) Index is out of range. Array<T>(columns: \(columns), rows:\(rows))")
      precondition(row < rows, "Row \(row) Index is out of range. Array<T>(columns: \(columns), rows:\(rows))")
      array[row*columns + column] = newValue
    }
  }
}

//显示提示
struct UserPrompter {
    func printIntroduction() {
        print("这是一个用来计算双蛋问题的小程序")
    }
    
    func printPrompt() {
        print("\n> ", terminator: "")
    }
    
   func promptForFloors() {
       print("\n输入楼层数: ", terminator: "")
    printPrompt()
   }
    
    func promptForEggs() {
        print("\n输入鸡蛋数: ", terminator: "")
        printPrompt()
    }
    func promptForOutPutType() {
        print("\n选择结果输出方式:1,输出全部表格;2,只显示目标结果 ", terminator: "")
        printPrompt()
    }
}

//输入状态
enum ApplicationState {
    case waitingForFloorsInputState
    case waitingForEggsInputState
    case waitingForTypeInputState
}


class StateMachine {
    var currentState = ApplicationState.waitingForFloorsInputState
    let standardInputFileHandle = FileHandle.standardInput
    let prompter = UserPrompter()
    var tFloors = 1
    var nEggs = 1
    
    //处理输入信息
    func runProcessingInput() {
        setbuf(stdout, nil)
        standardInputFileHandle.readabilityHandler = { (fileHandle: FileHandle) in
            let data = fileHandle.availableData
            DispatchQueue.main.async {
                self.handleUserInput(data)
            }
        }
        
        prompter.printIntroduction()
        prompter.promptForFloors()
        currentState = .waitingForFloorsInputState
       
        RunLoop.current.run() //
    }
    
    // 设置楼层
    func setupFloorsWithSelectionString(_ selectionString: String) -> Bool {
        var selectionString = selectionString
        selectionString = selectionString.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
        if let floors = Int(selectionString),floors > 0{
            tFloors = floors
             print("楼层数设置为: \(tFloors)", terminator: "")
            prompter.promptForEggs()
        return true
        } else {
            return false
        }
    }
    //设置鸡蛋
    func setEggsWithString(_ selectionString: String) -> Bool {
        var selectionString = selectionString
        selectionString = selectionString.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
        if let eggs = Int(selectionString),eggs > 0 {
            nEggs = eggs
            print("鸡蛋数设置为: \(eggs)", terminator: "")
            prompter.promptForOutPutType()
                return true
        } else {
            return false
        }
    }
    //根据楼层数,鸡蛋数,以及选择的显示方法显示结果
    func setTypeWithString(_ selectionString: String) -> Bool {
        var selectionString = selectionString
        selectionString = selectionString.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
        if let type = Int(selectionString) {
            if type == 1{
                DoubleEggs(tFloors: tFloors, nEggs: nEggs).printTable()
                print("\n\n\n重新开始")
                prompter.promptForFloors()
               return true
            }else if type == 2{
                DoubleEggs(tFloors: tFloors, nEggs: nEggs).printResult()
                print("\n\n\n重新开始")
                prompter.promptForFloors()
               return true
            }
            return false
        } else {
            return false
        }
    }
    
    // 处理输入数据
    func handleUserInput(_ dataFromUser: Data) {
        if let nsString = NSString(data: dataFromUser, encoding: String.Encoding.utf8.rawValue) {

            let string = nsString as String

            if string.lowercased().hasPrefix("exit") ||
                string.lowercased().hasPrefix("quit") {
                    print("Quitting...")
                    exit(EXIT_SUCCESS)
            }
            
            switch self.currentState {
            case .waitingForFloorsInputState:
                if !setupFloorsWithSelectionString(string){
                    print("\n错误:必须输入正确的楼层数。", terminator: "")
                    prompter.promptForFloors()
                    return;
                }
                currentState = .waitingForEggsInputState
                
            case .waitingForEggsInputState:
                if !setEggsWithString(string){
                    print("\n错误:必须输入正确的鸡蛋数。", terminator: "")
                    prompter.promptForEggs()
                    return
                }
                currentState = .waitingForTypeInputState
                

            case .waitingForTypeInputState:
                if !setTypeWithString(string){
                    print("\n错误:输入无效。", terminator: "")
                    prompter.promptForOutPutType()
                    return
                }
                currentState = .waitingForFloorsInputState
                
            }
        }
    }
    
    
    
    
}

StateMachine().runProcessingInput()

运行效果:

image.png
参考资料:
https://blog.csdn.net/u012803274/article/details/104824421
ORSSerialPort的CommandLineDemo
上一篇下一篇

猜你喜欢

热点阅读