美文网首页Swift编程
swift解决双蛋问题

swift解决双蛋问题

作者: iceger | 来源:发表于2020-03-15 13:06 被阅读0次

    双蛋问题:

    有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

    相关文章

      网友评论

        本文标题:swift解决双蛋问题

        本文链接:https://www.haomeiwen.com/subject/dedkehtx.html