■ このスレッドは過去ログ倉庫に格納されています
詰めswift
- 1 :デフォルトの名無しさん:2016/10/17(月) 07:26:01.96 ID:Cfbu+94c.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 :デフォルトの名無しさん:2016/10/17(月) 07:26:43.92 ID:Cfbu+94c.net
- 例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とかでは上手くかけなかった
- 3 :デフォルトの名無しさん:2016/10/17(月) 23:41:21.25 ID:OlRB0UDA.net
- var i = 1;
var sum = 0;
while i < 100 {
sum += i * i;
i += 2;
}
独りよがりで病的な書き方すんな
昔だったら>>1の母ですとか>>1の保護者ですとかでスレが埋まってたところだ
- 4 :デフォルトの名無しさん:2016/10/18(火) 01:45:25.16 ID:j9lDw9lO.net
- アイちゃんもSwift始めたの?
- 5 :デフォルトの名無しさん:2016/10/18(火) 09:12:27.14 ID:iz/6UNT/.net
- >>3
わかりやすけど、ダセーよ
- 6 :デフォルトの名無しさん:2016/10/18(火) 12:34:25.63 ID:XNeT8UDO.net
- >>3
ver sum=0
for i in stride(from: 1, to: 100, by: 2) {
sum += i * i
}
ちょっとc風味にしてみた
- 7 :デフォルトの名無しさん:2016/10/19(水) 01:22:25.18 ID:/23Ql8Gg.net
- 全然C風味じゃない件
まだ>>3のほうがセミコロンもついてるしよっぽどC
しかもverだしSwiftとしても失格
- 8 :デフォルトの名無しさん:2016/10/19(水) 08:03:16.58 ID:dprVW7hZ.net
- うるせーだまれ
- 9 :デフォルトの名無しさん:2016/10/19(水) 12:38:30.77 ID:opBPzs7C.net
- >>1
Arrayとfilterはstrideで、mapとreduceはreduce一発で書けるから
let a=stride(from:1, to:100, by:2).reduce(0){$0+$1*$1}
でいかが?
コンパイラに直値166650に置き換えられちゃうだろうけど
- 10 :デフォルトの名無しさん:2016/10/19(水) 22:05:18.41 ID:qqi+vVKd.net
- 可読性が高いSwiftねぇ…。
- 11 :デフォルトの名無しさん:2016/10/19(水) 22:14:25.11 ID:5poS2Bi0.net
- $が目障りなのはきっとSwiftのせい
このモダン言語どこに向かってるんだ
- 12 :デフォルトの名無しさん:2016/10/20(木) 18:00:58.36 ID:cE7OLI6Z.net
- 引数のビット長に応じた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)) )
コードから意図が読み取れる気がしない、、、
もう少しわかりやすい書き方ないかなぁ?
- 13 :デフォルトの名無しさん:2016/10/20(木) 18:06:16.70 ID:+R+Vhl1P.net
- 関数名が悪いのと、ドキュメントコメントがないのが悪い
と見も蓋もないこと言ってみるテスト
可読性無視して如何に短くかけるか挑戦しようぜ
- 14 :デフォルトの名無しさん:2016/10/21(金) 00:07:12.34 ID:l5tk1soN.net
- >>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:
- 15 :デフォルトの名無しさん:2016/10/21(金) 00:09:13.94 ID:l5tk1soN.net
- なんか上手くかけなかった
テスト
let fmtStr = [1:"%02hhx",2:"%04hx",4:"%08lx",8:"%016llx"]
テストここまで
- 16 :デフォルトの名無しさん:2016/10/21(金) 00:10:44.13 ID:l5tk1soN.net
- 再投稿
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)) )
- 17 :デフォルトの名無しさん:2016/10/21(金) 00:16:57.99 ID:l5tk1soN.net
- >>16
投稿成功
ただ、formatは型安全じゃないのでString(val, radix:16)を使う方がswiftらしいと思うな
- 18 :デフォルトの名無しさん:2016/10/21(金) 00:46:56.25 ID:l5tk1soN.net
- >>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()って頭詰には使えないのか?使えたらもう少し綺麗に書けるのだけど
- 19 :デフォルトの名無しさん:2016/10/21(金) 22:02:05.01 ID:TQyRjkJz.net
- >>18
func toHex<T:UnsignedInteger>(_ val:T)->String{
return String(("0000000000000000"+String(val,radix:16)).characters.suffix(2*MemoryLayout<T>.size))
}
- 20 :デフォルトの名無しさん:2016/10/22(土) 10:03:25.21 ID:KGTzT2v9.net
- Swift読みにく...
- 21 :デフォルトの名無しさん:2016/10/22(土) 11:44:17.58 ID:2eM+QRLE.net
- Swiftって他と違う感を無駄に追い求めすぎて読みにくいよな
べジータ親父ラットナーのセンスが無さすぎ
- 22 :デフォルトの名無しさん:2016/10/24(月) 14:52:18.58 ID:H58quMwb.net
- >>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)}
- 23 :デフォルトの名無しさん:2016/10/25(火) 07:22:49.90 ID:TTNTJAzx.net
- Swiftのfuncの記法、ほんっときったねぇよな
読みにくすぎてセンスを全く感じない
- 24 :デフォルトの名無しさん:2016/10/25(火) 11:46:02.76 ID:TDuxU4Gc.net
- 別にこのような記法で書く必然性はないわけだが…
読みにくいって言ってる奴は、お前が思う普通に書けばいいわけで
バカの子なの?
- 25 :デフォルトの名無しさん:2016/10/26(水) 02:45:17.64 ID:NtHQYyX3.net
- >>24
文法的な話かと
改行位置とかインデントとかそういう話じゃない
- 26 :デフォルトの名無しさん:2016/10/26(水) 20:49:07.50 ID:Bins4IAo.net
- >>25
例えばどんなとこが気持ち悪いのかがわからん
- 27 :デフォルトの名無しさん:2016/10/26(水) 22:07:07.78 ID:xhdxFtWZ.net
- 例えばその例で言うとラベル付き引数funcの汚さとか
ただてさえ変数型が:後置でカオスなのにさらにアンダースコアで省略とか複合するとクソさが増す
ObjCはあくまでセレクタ名をラベルとして使ってるシンプルさとは可読性が雲泥の差
ラットナーのセンスがないとしか言いようがない
- 28 :デフォルトの名無しさん:2016/10/26(水) 23:14:32.89 ID:Bins4IAo.net
- それはお前の好き嫌いとか慣れの問題だろ
別に見づらくねーし、省略はいやなら使わなければ良い
つーかスレチだからアンチスレで熱く語ってくれよ
- 29 :デフォルトの名無しさん:2016/10/27(木) 07:08:22.73 ID:Ss0lD5+4.net
- 新しい言語を覚えたらまずハノイの塔をやってみるといいよ
ってじっちゃが言ってた
swiftの値付きenumが割と好き
enum pole:String{
case a =
- 30 :デフォルトの名無しさん:2016/10/27(木) 07:08:50.35 ID:Ss0lD5+4.net
- 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)
- 31 :デフォルトの名無しさん:2016/10/28(金) 07:07:02.16 ID:MsjgJgue.net
- >>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のポールを判断させればいいので
と思ったが帰って長くなってしまった
- 32 :デフォルトの名無しさん:2016/10/28(金) 07:09:17.73 ID:MsjgJgue.net
- 今回気づいたけどenumの全要素でイテレートするとか、全要素のSetやArrayを作るとか簡単にはできないんだね
StackOverflowで熱く議論されていた
地味に不便
- 33 :デフォルトの名無しさん:2016/10/28(金) 13:12:32.29 ID:1V3HImWP.net
- Julia 最強説
- 34 :デフォルトの名無しさん:2016/10/29(土) 08:55:14.86 ID:ehT37hdT.net
- >>22
>>2
多分Intだけが特殊でジェネリックやりにくいんだろうね
エンディアンに関してはInt8だけが仲間ハズレ
- 35 :デフォルトの名無しさん:2016/11/01(火) 19:17:48.49 ID:SqrJLIAe.net
- >>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は適当に作ってくれ
- 36 :デフォルトの名無しさん:2016/11/05(土) 17:15:15.00 ID:i8zaQxL9.net
- >>35
誤記が多いっす。まさかコピペじゃなくて手打ち?
import Foundation
func toHex<T:UnsignedInteger>(_ val:T)->String{
return String((
- 37 :デフォルトの名無しさん:2016/11/05(土) 17:18:16.62 ID:i8zaQxL9.net
- 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行
あと、この方がキャラクター表示とかの拡張もやりやすいと思う
データはファイルアクセスが面倒臭かったので、コード内で連番で生成
- 38 :デフォルトの名無しさん:2016/11/06(日) 10:21:57.41 ID:fH2uMvYe.net
- >>37
var d = Data(bytes: [UInt8](0...250))
こっちの方が5文字省略できる
- 39 :デフォルトの名無しさん:2016/11/06(日) 13:03:30.79 ID:UB8ayWaX.net
- >>29-30
2chのバグだろう
書き込み確認画面が出る際、" を使うと、そこで文字列の終了とみなされる。
" の代わりに、\" とエスケープすれば、どうだろう?
- 40 :デフォルトの名無しさん:2016/11/07(月) 21:43:08.46 ID:YiAcxNVS.net
- なるほど
時々playgroundにペーストしても動かないコードがあると思った
- 41 :デフォルトの名無しさん:2016/11/08(火) 08:53:41.63 ID:X5dOVA43.net
- >>37
d[i...min(i+16,d.count)-1]
は
d[i..<min(i+16,d.count)]
の方が2文字省略できるし意図が明確になるので俺は好き
- 42 :デフォルトの名無しさん:2016/11/09(水) 08:16:54.26 ID:lBjkYqNx.net
- なんだこと汚い字面は
- 43 :デフォルトの名無しさん:2016/11/09(水) 13:32:04.04 ID:WltZpkeV.net
- >>1
例1は誰も具体的な型を指定していないので型推論に失敗する
全ての可能性を確認した後で配列の初期化子のRangeがカウンタブルなのを見て、整数型と推論したんじゃ無いかな?
だから、推論の段数が深くなるとコンパイラが根を上げる
Array<Int>または[Int]で要素の型を明示して配列を初期化してやれば、普通にコンパイルできる
let a = [Int](1...100).lazy.filter{$0%2==1}.map{$0*$0}.reduce(0){$0+$1}
最近見かけたlazyを入れて見た
いいものらしいが、実はまだ使い方がよくわかってない
- 44 :デフォルトの名無しさん:2016/11/17(木) 23:03:23.42 ID:nPsJ1cdA.net
- >>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
}
}
ジェネリクスのめんどくさいところと、関数オーバーロードのメンテ性の悪さ
両方を兼ね備えてみました
無駄なプロトコル定義しなくて済むけどイマイチかっこいくないな
- 45 :デフォルトの名無しさん:2016/11/18(金) 12:36:36.52 ID:slfuYiby.net
- >>44
自己レス
これ、caseとdefaultを逆にして
UInt8だけを除け者にしようとしたら
defaultの中でエンディアン指定の初期化なんて知らないもんね
って言われた
そりゃそうなんだけどさ
エンディアン指定初期化をくくるプロトコルを標準で入れてくれ!!
IntegerTypeに入れてもいいぞ、8bitの時はそのままの値で
あとは、リフレクションで出来るかどうかだな
動的になっちゃうけど
Swiftのリフレクションて何ができるのかな?
- 46 :デフォルトの名無しさん:2016/12/12(月) 06:38:11.91 ID:y+Doho0R.net
- ズンドコしてみますた
import Foundation
func ズンドコ()->String{return arc4random_uniform(2)==0 ?
- 47 :デフォルトの名無しさん:2016/12/12(月) 06:39:28.62 ID:y+Doho0R.net
- ズンドコしてみますた
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で代用
無限ループを乱数で抜ける&履歴切り捨てが無いので条件によっては運が悪いとクラッシュするかも
- 48 :デフォルトの名無しさん:2018/05/23(水) 22:41:40.90 ID:Au5e7VGg.net
- 僕の知り合いの知り合いができたパソコン一台でお金持ちになれるやり方
役に立つかもしれません
グーグルで検索するといいかも『ネットで稼ぐ方法 モニアレフヌノ』
7YIPP
- 49 :デフォルトの名無しさん:2018/07/04(水) 23:25:26.40 ID:gFgZc5FG.net
- MV8
総レス数 49
20 KB
掲示板に戻る
全部
前100
次100
最新50
read.cgi ver 2014.07.20.01.SC 2014/07/20 D ★