詰めswift [無断転載禁止]©2ch.net
■ このスレッドは過去ログ倉庫に格納されています
swiftらしい簡潔な書き方を追求するスレ 昔「詰めvi」というスレが好きだったので立ててみました。 [出題者] ・問題を定義。実現したい機能、データ構造、制約条件等を簡潔に記載 ・自分の解答例のコードを記載。この時点ではへぼいコードでも問題ないです ・自分の解答例への感想、改善要望等の記載推奨。工夫した点、不満な点(もう少しこうしたい)、こう書けるはずなのにエラーになったなど [挑戦者] ・出題に対して「俺ならこう書く」というのをコードで回答 お約束 ・コードで語ろう 投稿は実際に動作するコードを付けることを原則とします。 「この書き方は好き」とか複数の投稿済みコードに対して「こちらの方がSwiftらしい」みたいなことはコード無しでもOK。 他の人を批判する場合は必ずそれに相応する動作可能コードを付けること。 ・コード無しでディスるだけの人は徹底無視 ・投稿するコードはXCode8のプレイグラウンドまたは”IBM Swift Sandbox”にペーストしてそのまま動作すること ・環境は当面Swift3ベース、Swift Standard Library、Foundation Libraryの範囲とします。 異なる場合は動作環境を明記のこと。 評価基準 ・swiftらしい書き方かどうか 簡潔性、直交性等 ・意図が明確か ・短いは正義 例1 1から100までの奇数の2乗の合計を求める let a = Array(1...100).filter{$0%2==1}.map{$0*$0} let b = a.reduce(0){$0+$1} 1行で書きたかったがplaygroundがエラーになった 例2 汎用的なエンディアン変換 protocol BoCInititializable { associatedtype BaseType init(littleEndian: BaseType) init(bigEndian: BaseType) } extension UInt16: BoCInititializable{} extension UInt32: BoCInititializable{} extension UInt64: BoCInititializable{} extension UInt: BoCInititializable{} func bth<T:BoCInititializable>(_ v:T)->T { return T(bigEndian: v as! T.BaseType) } func lth<T:BoCInititializable>(_ v:T)->T { return T(littleEndian: v as! T.BaseType) } print( bth(UInt32(1)) ) もう少し簡潔に書きたいがunsignedintegerとかでは上手くかけなかった var i = 1; var sum = 0; while i < 100 { sum += i * i; i += 2; } 独りよがりで病的な書き方すんな 昔だったら>>1 の母ですとか>>1 の保護者ですとかでスレが埋まってたところだ >>3 ver sum=0 for i in stride(from: 1, to: 100, by: 2) { sum += i * i } ちょっとc風味にしてみた 全然C風味じゃない件 まだ>>3 のほうがセミコロンもついてるしよっぽどC しかもverだしSwiftとしても失格 >>1 Arrayとfilterはstrideで、mapとreduceはreduce一発で書けるから let a=stride(from:1, to:100, by:2).reduce(0){$0+$1*$1} でいかが? コンパイラに直値166650に置き換えられちゃうだろうけど $が目障りなのはきっとSwiftのせい このモダン言語どこに向かってるんだ 引数のビット長に応じた0詰を行う16進変換 import Foundation func toHex<T:UnsignedInteger>(_ val:T)->String { let hexLen=MemoryLayout<T>.size * 2 return String(format:"%0\(hexLen)x", val as! CVarArg) } print( toHex(UInt16(253)) ) コードから意図が読み取れる気がしない、、、 もう少しわかりやすい書き方ないかなぁ? 関数名が悪いのと、ドキュメントコメントがないのが悪い と見も蓋もないこと言ってみるテスト 可読性無視して如何に短くかけるか挑戦しようぜ >>12 %xは32ビットの変換指定子なのでこのままだと64ビットの時上手く動かないよ %llxを使おう←とりあえず動くと思う 厳密にやるなら%hhx、%hx、%lx、%llxを使い分けなきゃいけない import Foundation func toHex<T:UnsignedInteger>(_ val:T)->String { let byteLen=MemoryLayout<T>.size let fmtStr = [1: なんか上手くかけなかった テスト let fmtStr = [1:"%02hhx",2:"%04hx",4:"%08lx",8:"%016llx"] テストここまで 再投稿 import Foundation func toHex<T:UnsignedInteger>(_ val:T)->String { let byteLen=MemoryLayout<T>.size let fmtStr = [1:"%02hhx",2:"%04hx",4:"%08lx",8:"%016llx"] return String(format:fmtStr[byteLen]!, val as! CVarArg) } print( toHex(UInt8(0x0f)) ) print( toHex(UInt16(0x01ff)) ) print( toHex(UInt32(0x010000ff)) ) print( toHex(UInt64(0x01000000000000ff)) ) >>16 投稿成功 ただ、formatは型安全じゃないのでString(val, radix:16)を使う方がswiftらしいと思うな >>16 func toHex<T:UnsignedInteger>(_ intVal:T)->String{ let byteLen=MemoryLayout<T>.size let hexStr=String(intVal, radix:16) return String(repeating:"0",count:byteLen*2-hexStr.characters.count)+hexStr } こっちの方がミスらないと思う Foundationのimportも要らないし しかしString.padding()って頭詰には使えないのか?使えたらもう少し綺麗に書けるのだけど >>18 func toHex<T:UnsignedInteger>(_ val:T)->String{ return String(("0000000000000000"+String(val,radix:16)).characters.suffix(2*MemoryLayout<T>.size)) } Swiftって他と違う感を無駄に追い求めすぎて読みにくいよな べジータ親父ラットナーのセンスが無さすぎ >>2 頑張ってジェネリクスにするよりも関数オーバーロードの方が見かけはシンプルに書けるよ ただ、バイトオーダー変換が必要な処理は強烈にビット長を意識するべき処理な訳で そこをビット長汎用化する意味があるのかという所の方が問題なきがする ま「詰めSwift」と言うお遊びの中での解の一つとして func bth(_ v:UInt16)->UInt16{return UInt16(bigEndian: v)} func bth(_ v:UInt32)->UInt32{return UInt32(bigEndian: v)} func bth(_ v:UInt64)->UInt64{return UInt64(bigEndian: v)} func bth(_ v:UInt)->UInt{return UInt(bigEndian: v)} func lth(_ v:UInt16)->UInt16{return UInt16(littleEndian: v)} func lth(_ v:UInt32)->UInt32{return UInt32(littleEndian: v)} func lth(_ v:UInt64)->UInt64{return UInt64(littleEndian: v)} func lth(_ v:UInt)->UInt{return UInt(littleEndian: v)} Swiftのfuncの記法、ほんっときったねぇよな 読みにくすぎてセンスを全く感じない 別にこのような記法で書く必然性はないわけだが… 読みにくいって言ってる奴は、お前が思う普通に書けばいいわけで バカの子なの? >>24 文法的な話かと 改行位置とかインデントとかそういう話じゃない >>25 例えばどんなとこが気持ち悪いのかがわからん 例えばその例で言うとラベル付き引数funcの汚さとか ただてさえ変数型が:後置でカオスなのにさらにアンダースコアで省略とか複合するとクソさが増す ObjCはあくまでセレクタ名をラベルとして使ってるシンプルさとは可読性が雲泥の差 ラットナーのセンスがないとしか言いようがない それはお前の好き嫌いとか慣れの問題だろ 別に見づらくねーし、省略はいやなら使わなければ良い つーかスレチだからアンチスレで熱く語ってくれよ 新しい言語を覚えたらまずハノイの塔をやってみるといいよ ってじっちゃが言ってた swiftの値付きenumが割と好き enum pole:String{ case a = enum pole:String{ case a = "a" case b = "b" case c = "c" } func hanoi(num:Int, from:pole, to:pole, workWith:pole)->[(pole,pole)]{ var operation:[(pole,pole)]=[] if num == 1 { operation+=[(from,to)] } else { operation += hanoi(num:num-1, from:from, to:workWith, workWith:to) operation += hanoi(num:1, from:from, to:to, workWith:workWith) operation += hanoi(num:num-1, from:workWith, to:to, workWith:from) } return operation } let moveList = hanoi(num:9, from:pole.a, to:pole.b, workWith:pole.c) print(moveList.count) print(moveList) >>30 enum pole:String{ case a,b,c static func restOf(_ a1:pole, _ a2:pole)->pole { var allValue:Set<pole> = [.a,.b,.c] allValue.remove(a1) allValue.remove(a2) return allValue.first! } } func hanoi(num:Int, from:pole, to:pole)->[(pole,pole)]{ var operation:[(pole,pole)]=[] if num == 1 { operation+=[(from,to)] } else { operation += hanoi(num:num-1, from:from, to:.restOf(from,to)) operation += hanoi(num:1, from:from, to:to) operation += hanoi(num:num-1, from:.restOf(from,to), to:to) } return operation } let moveList = hanoi(num:3, from:.a, to:.b) print(moveList.count) print(moveList) String型enumは値を指定しないとenum名が値になるので省略化 workWithはenum自身に第3のポールを判断させればいいので と思ったが帰って長くなってしまった 今回気づいたけどenumの全要素でイテレートするとか、全要素のSetやArrayを作るとか簡単にはできないんだね StackOverflowで熱く議論されていた 地味に不便 >>22 >>2 多分Intだけが特殊でジェネリックやりにくいんだろうね エンディアンに関してはInt8だけが仲間ハズレ >>29 最初はヘキサダンプだべって、ばっちゃが import Foundation func toHex<T:UnsignedInteger>(_ val:T)->String{ return String(("0000000000000000"+String(val,radix:16)).characters.suffix(2*MemoryLayout<T>.size)) } var fileURL = xxxxxxxxxx var d = try! Data(contentOf: fileURL) for (i,e) in d.enumrated() { if i%16==0 {print(toHex(i)),terminator:": ")} print(toHex(e),terminator:" ") if i%16==15 {print()} } toHex()はこのスレのもらい物 fileURLは適当に作ってくれ >>35 誤記が多いっす。まさかコピペじゃなくて手打ち? import Foundation func toHex<T:UnsignedInteger>(_ val:T)->String{ return String(( import Foundation func toHex<T:UnsignedInteger>(_ val:T)->String{ return String(("0000000000000000"+String(val,radix:16)).characters.suffix(2*MemoryLayout<T>.size)) } var d = Data(bytes: Array<UInt8>(0...250)) // making dummy data for i in stride(from:0, to:d.count, by:16) { print(toHex(UInt(i))+d[i...min(i+16,d.count)-1].reduce(":"){$0+" "+toHex($1)}) } 表示1行分ずつアクセスした方がif文とか不要で簡単 これでfor文内1行 あと、この方がキャラクター表示とかの拡張もやりやすいと思う データはファイルアクセスが面倒臭かったので、コード内で連番で生成 >>37 var d = Data(bytes: [UInt8](0...250)) こっちの方が5文字省略できる >>29-30 2chのバグだろう 書き込み確認画面が出る際、" を使うと、そこで文字列の終了とみなされる。 " の代わりに、\" とエスケープすれば、どうだろう? なるほど 時々playgroundにペーストしても動かないコードがあると思った >>37 d[i...min(i+16,d.count)-1] は d[i..<min(i+16,d.count)] の方が2文字省略できるし意図が明確になるので俺は好き >>1 例1は誰も具体的な型を指定していないので型推論に失敗する 全ての可能性を確認した後で配列の初期化子のRangeがカウンタブルなのを見て、整数型と推論したんじゃ無いかな? だから、推論の段数が深くなるとコンパイラが根を上げる Array<Int>または[Int]で要素の型を明示して配列を初期化してやれば、普通にコンパイルできる let a = [Int](1...100).lazy.filter{$0%2==1}.map{$0*$0}.reduce(0){$0+$1} 最近見かけたlazyを入れて見た いいものらしいが、実はまだ使い方がよくわかってない >>22 バイトオーダー変換 func bth<T:UnsignedInteger>(_ v:T)->T{ switch v { case let u as UInt16: return type(of:u).init(bigEndian:u) as! T case let u as UInt32: return type(of:u).init(bigEndian:u) as! T case let u as UInt64: return type(of:u).init(bigEndian:u) as! T case let u as UInt : return type(of:u).init(bigEndian:u) as! T default: return v } } func lth<T:UnsignedInteger>(_ v:T)->T{ switch v { case let u as UInt16: return type(of:u).init(littleEndian:u) as! T case let u as UInt32: return type(of:u).init(littleEndian:u) as! T case let u as UInt64: return type(of:u).init(littleEndian:u) as! T case let u as UInt : return type(of:u).init(littleEndian:u) as! T default: return v } } ジェネリクスのめんどくさいところと、関数オーバーロードのメンテ性の悪さ 両方を兼ね備えてみました 無駄なプロトコル定義しなくて済むけどイマイチかっこいくないな >>44 自己レス これ、caseとdefaultを逆にして UInt8だけを除け者にしようとしたら defaultの中でエンディアン指定の初期化なんて知らないもんね って言われた そりゃそうなんだけどさ エンディアン指定初期化をくくるプロトコルを標準で入れてくれ!! IntegerTypeに入れてもいいぞ、8bitの時はそのままの値で あとは、リフレクションで出来るかどうかだな 動的になっちゃうけど Swiftのリフレクションて何ができるのかな? ズンドコしてみますた import Foundation func ズンドコ()->String{return arc4random_uniform(2)==0 ? ズンドコしてみますた import Foundation func ズンドコ()->String{return arc4random_uniform(2)==0 ? "ズン" : "ドコ"} let 期待値="ズンズンズンズンドコ" var 履歴=String() while(true){ let 今回=ズンドコ() print(今回) 履歴.append(今回) if 履歴.hasSuffix(期待値){ print("キ・ヨ・シ・!") break } } http://swiftlang.ng.bluemix.net/#/repl/584dc645c1c4e155aaee6ac6 IBM Sandboxはarc4random系が無いみたいなのでrand()%2で代用 無限ループを乱数で抜ける&履歴切り捨てが無いので条件によっては運が悪いとクラッシュするかも 僕の知り合いの知り合いができたパソコン一台でお金持ちになれるやり方 役に立つかもしれません グーグルで検索するといいかも『ネットで稼ぐ方法 モニアレフヌノ』 7YIPP ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.0 2024/04/24 Walang Kapalit ★ | Donguri System Team 5ちゃんねる