📌
割り勘計算 アルゴリズムの作成 in Swift
今回作るアルゴリズム
input Data
1. A が A,C,D 3人分 1200円払った
3. B が A,B,C,D 4人分 2400円払った
4. C が A,B,C 3人分 3000円払った
のようなデータを入れると
output Data
1. D から C に 1000円渡してください
2. A から B に 800円渡してください
という形で計算できるコードを書いていこうと思います。
作成の主な流れ
- input Dataをうまく扱えるようにする!
- output Dataの形も決定する
- アルゴリズム作成
- なぜ頭で考えたらわかるのか?
- 言語化 + 紙などに書いて実際に自分がどう計算しているのか?理解する
アルゴリズムの計算流れ
- 誰が何円損得している状態なのか?をinput Dataから計算する
- 損得同じなのであればそこで金銭取引を決定
- 同じ金額がなさそうであれば損得金額が大きい順に金銭取引を進める
- 最後に取引金額、人を出力する
実際の計算
誰が何円損得している状態なのか?をinput Dataから計算する
var outVolvesData: Dictionary<String, Int> = [:]
for i in memberName{
outVolvesData[i] = 0
}
for data in history {
var amount: Int = data.amount
var payer: String = data.payer
var involves: [String] = data.involves
let payNum = Int(amount/involves.count)
for member in involves {
if payer == member{
outVolvesData[member]! -= payNum*(involves.count-1)
continue
}
outVolvesData[member]! += payNum
}
損得同じなのであればそこで金銭取引を決定
未実装
同じ金額がなさそうであれば損得金額が大きい順に金銭取引を進める
var sortOutVolves = outVolvesData.sorted(by: { $0.value > $1.value })
var pulsOutVolvesData: Dictionary<String, Int> = [:]
var mainsOutVolvesData: Dictionary<String, Int> = [:]
var ans_Ay:[PayersDecision] = []
for data in sortOutVolves{
if data.value >= 0{
pulsOutVolvesData[data.key] = data.value
}else{
mainsOutVolvesData[data.key] = data.value
}
}
var pulsOutVolvesDataBeta:[[Any]] = []
for i in pulsOutVolvesData.sorted(by: { $0.value > $1.value }){
pulsOutVolvesDataBeta.append([i.key, i.value])
}
var mainsOutVolvesDataBeta:[[Any]] = []
for i in mainsOutVolvesData.sorted(by: { $0.value < $1.value }){
mainsOutVolvesDataBeta.append([i.key, i.value])
}
pulsOutVolvesDataBeta.sort{$0[1] as! Int > $1[1] as! Int}
mainsOutVolvesDataBeta.sort{$0[1] as! Int > $1[1] as! Int}
mainsOutVolvesDataBeta.reverse()
for mainsOutVolve in mainsOutVolvesDataBeta{
var value = mainsOutVolve[1] as! Int
pulsOutVolvesDataBeta.sort{$0[1] as! Int > $1[1] as! Int}
for (num,plusOutVole) in pulsOutVolvesDataBeta.enumerated(){
let watasimasita:Int = plusOutVole[1] as! Int + value
if watasimasita >= 0 {
pulsOutVolvesDataBeta[num][1] = watasimasita
ans_Ay.append(PayersDecision(outVolves: abs(value) ,payer: plusOutVole[0] as! String,target:mainsOutVolve[0] as! String))
value = 0
break
}else{
value = watasimasita
pulsOutVolvesDataBeta[num][1] = 0
ans_Ay.append(PayersDecision(outVolves: plusOutVole[1] as! Int ,payer: plusOutVole[0] as! String,target:mainsOutVolve[0] as! String))
continue
}
}
}
最後に取引金額、人を出力する
for i in ans_Ay{
print("決定だよ〜〜")
D から C に 1000円渡してください
print("\(i.payer!)から\(i.target!)へ\(i.outVolves!)円渡してください")
}
最後に作成した関数
input output など使用しやすくした型
class PayHis: NSObject{
var amount: Int!
var payer: String!
var involves: [String]!
init(amount: Int,payer: String,involves: [String]) {
self.amount = amount
self.payer = payer
self.involves = involves
}
}
class PayersDecision: NSObject{
var payer: String!
var target: String!
var outVolves: Int!
init(outVolves: Int,payer: String,target:String) {
self.outVolves = outVolves
self.payer = payer
self.target = target
}
}
実装関数
func calclateGroupPay(history: [PayHis],memberName:[String]) {
var outVolvesData: Dictionary<String, Int> = [:]
for i in memberName{
outVolvesData[i] = 0
}
for data in history {
var amount: Int = data.amount
var payer: String = data.payer
var involves: [String] = data.involves
let payNum = Int(amount/involves.count)
for member in involves {
if payer == member{
outVolvesData[member]! -= payNum*(involves.count-1)
continue
}
outVolvesData[member]! += payNum
}
}
var sortOutVolves = outVolvesData.sorted(by: { $0.value > $1.value })
var pulsOutVolvesData: Dictionary<String, Int> = [:]
var mainsOutVolvesData: Dictionary<String, Int> = [:]
var ans_Ay:[PayersDecision] = []
for data in sortOutVolves{
if data.value >= 0{
pulsOutVolvesData[data.key] = data.value
}else{
mainsOutVolvesData[data.key] = data.value
}
}
var pulsOutVolvesDataBeta:[[Any]] = []
for i in pulsOutVolvesData.sorted(by: { $0.value > $1.value }){
pulsOutVolvesDataBeta.append([i.key, i.value])
}
var mainsOutVolvesDataBeta:[[Any]] = []
for i in mainsOutVolvesData.sorted(by: { $0.value < $1.value }){
mainsOutVolvesDataBeta.append([i.key, i.value])
}
pulsOutVolvesDataBeta.sort{$0[1] as! Int > $1[1] as! Int}
mainsOutVolvesDataBeta.sort{$0[1] as! Int > $1[1] as! Int}
mainsOutVolvesDataBeta.reverse()
for mainsOutVolve in mainsOutVolvesDataBeta{
var value = mainsOutVolve[1] as! Int
pulsOutVolvesDataBeta.sort{$0[1] as! Int > $1[1] as! Int}
for (num,plusOutVole) in pulsOutVolvesDataBeta.enumerated(){
let watasimasita:Int = plusOutVole[1] as! Int + value
if watasimasita >= 0 {
pulsOutVolvesDataBeta[num][1] = watasimasita
ans_Ay.append(PayersDecision(outVolves: abs(value) ,payer: plusOutVole[0] as! String,target:mainsOutVolve[0] as! String))
value = 0
break
}else{
value = watasimasita
pulsOutVolvesDataBeta[num][1] = 0
ans_Ay.append(PayersDecision(outVolves: plusOutVole[1] as! Int ,payer: plusOutVole[0] as! String,target:mainsOutVolve[0] as! String))
continue
}
}
}
for i in ans_Ay{
print("決定だよ〜〜")
print("\(i.payer!)から\(i.target!)へ\(i.outVolves!)円渡してください")
}
}
Discussion