双蛋问题:
有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
网友评论