Tips untuk bermain golf di Swift

24

Apa saja tips untuk bermain golf kode di Swift? Fokusnya pada keamanan tampaknya membuatnya sulit untuk bermain golf, tetapi itu membuat sedikit tips dan bahkan lebih bermanfaat. Apakah ada fitur di Swift yang dapat membantunya unggul dalam kode-golf pada aplikasi tertentu?

Silakan kirim satu tip per jawaban.

addison
sumber
11
Anda dapat mengandalkan kami - jika itu dimaksudkan untuk aman, itu akan menjadi d̶a̶n̶g̶e̶r̶o̶u̶s̶ golfy!
Conor O'Brien
9
Semoga beberapa tips bagus masuk dengan cepat.
DJMcMayhem
4
Golf cepat? Saya pikir golf seharusnya menjadi permainan yang lambat dan tenang ...
Jojodmo

Jawaban:

6

Kisaran

Satu hal yang sangat membantu adalah membuat rentang menggunakan operator ...atau..<

Sebagai contoh

array[0..<n] //first n elements of array
array[k..<n] //kth through nth elements of array
array[k...n] //kth through n-1 elements of array

Jadi, untuk mendapatkan nilai array 2 hingga 4

let myArray = ["ab", "cd", "ef", "gh", "ij", "kl", "mn", "op"]
print(myArray[1..<4]) //["cd", "ef", "gh"]

Penggunaan Praktis

let a = [3, 1, 4, 1, 5, 9]

Menggunakan

for v in a[0...3]{print(v)}

Lebih pendek 8 byte dari

for n in 0...3{let v=a[n];print(v)}
Jojodmo
sumber
4
... for n in 0...3{print(a[n])}tidak valid?
Julian Wolf
4

Penutupan:

Penggunaan variabel fungsi terus vs menggunakan fungsi itu sendiri dapat membantu:

65 byte:

var r:(String,Int)->String={return String(repeating:$0,count:$1)}

66 byte:

func r(s:String,i:Int)->String{return String(repeating:s,count:i)}

Perbedaan kecil di sini, tetapi akan lebih banyak muncul di beberapa teka-teki.

Fungsi Pemendekan:

Melihat contoh sebelumnya mengingatkan saya pada sesuatu. Kadang-kadang, jika Anda akan menggunakan suatu fungsi cukup kali, ada baiknya ruang untuk menamainya:

Ini:

String(repeating:$0,count:$1)

Untuk ini:

var r:(String,Int)->String={return String(repeating:$0,count:$1)}

Atau, sebenarnya, ini lebih baik:

var r=String.init(repeating:count:)

Dengan begitu Anda hanya menelepon r("Hello World",8)sajaString(repeating:"Hello World",count:8)

Meninggalkan Jenis Deklarasi:

Saya pernah membuat penutupan tanpa menetapkan jenis argumen, sehingga menciptakan jawaban yang lebih pendek:

var f={(i)->Int in i-1+i%2*2}

Kompilator menyimpulkan bahwa iada di Int.

Buat Array dengan Cara Cepat:

Jika Anda membutuhkan array Ints, gunakan a Rangeuntuk membuatnya:

Array(0...5)

Ini melakukan hal yang sama seperti:

[0,1,2,3,4,5]

Array Alih-alih Ifatau Switch:

Alih-alih melakukan ini:

if n==0{return "a"}else if n==1{return "b"}else{return "c"}

Anda mungkin dapat melakukan ini:

return ["a","b","c"][n]

Mempersingkat jenis:

Jika Anda sering menggunakan konversi jenis, Anda mungkin ingin membuat alias jenis:

typealias f=Float

Peta:

Ingatlah bahwa Anda sering tidak perlu menggunakan returnkata kunci dalam mapfungsi.

Menjalankan Swift Online:

Meskipun Try It Online tidak mendukung Swift It tidak sekarang !

Caleb Kleveter
sumber
2
Terima kasih untuk kirimannya. Banyak membantu saya. tio.run/nexus sekarang berfungsi dengan cepat :)
palme
3

try

Di Swift 2.x dan di atasnya, fungsi yang secara tradisional menangani kesalahan dengan meneruskan pointer ke NSErrorobjek sebagai parameter fungsi sekarang throwkesalahan mereka.

Ini berarti bahwa ini:

var regex = NSRegularExpression(pattern: "\"((http)s?://.*?)\"", options: nil, error: nil)

sekarang terlihat seperti:

do {
    let regex = try NSRegularExpression(pattern: "\"((http)s?://.*?)\"", options: [])
} catch {
    print(error)
}

Ini dapat disingkat dengan menggunakan try?atau try!. try?akan mengevaluasi ekspresi niljika ada kesalahan. try!akan membuat crash program Anda jika ada kesalahan, dan hanya akan digunakan jika tidak ada kesalahan yang terjadi.

let regex = try! NSRegularExpression(pattern: "\"((http)s?://.*?)\"", options: [])

try?dan try!simpan setidaknya 13 byte dari do-try-catchloop. Perhatikan bahwa Anda juga menyimpan setidaknya satu byte lagi dengan meneruskan array kosong ( []) untuk opsi alih-alih nil.

JAL
sumber
3

Mengurangi Array

Iterasi dengan for-in loopsmelalui array untuk mendapatkan nilai tunggal seperti jumlah elemen di dalam, atau produk elemennya mungkin terlalu lama untuk seberapa sederhana sebenarnya. Anda bisa menggunakan reduce()metode ini. Beberapa contoh:

var array = [1,2,3,4,5,6,7]

Menambahkan elemen dalam array dengan for-inloop:

var sum = 0

for item in array{
    sum += item
}
print(sum)

dapat disederhanakan untuk:

print(array.reduce(0, +))

Dan mendapatkan produk dari elemen-elemen di dalam array dengan for-in loop:

var multiplier = 1
for item in array{
    multiplier *= item
}
print(multiplier)

juga dapat direduksi menjadi:

print(array.reduce(1, *))
Tuan Xcoder
sumber
Tidakkah Anda kehilangan lebih banyak byte dengan mendeklarasikan **fungsinya daripada hanya dengan menelepon powsecara manual?
JAL
@ JAL ya, tetapi jika Anda memanggil pow 10 kali, itu menghemat sejumlah kecil byte. Bukan teknik golf terbaik, tapi itu hanya bantuan potensial. Itu tidak dimaksudkan untuk pow khusus, tetapi untuk operasi lain seperti mencari bilangan prima, jika Anda melakukannya 3 kali, itu menghemat sejumlah besar byte
Tn. Xcoder
2

Operator ternary Swift sangat singkat: condition ? action : otheraksi

Jika kondisinya benar, lakukan satu hal, jika tidak, lakukan sesuatu yang lain.

textColor = bgIsBlack ? .white : .black

Ini membuat textColorputih jika latar belakangnya hitam, atau hitam jika latar belakangnya adalah warna lain.

Operator penggabungan nihil bahkan lebih sulit: a ?? b

Katakanlah Anda sedang memeriksa JSON untuk kunci tertentu sehingga Anda dapat menyajikan nilai kunci sebagai teks judul. Jika kunci tidak ada (yaitu nilainya nihil), kami ingin memberikan teks judul default.

title = keysValue ?? "Not Available"
Martyav
sumber
2

Pencacahan

Anda dapat menghubungkan forEachdari enumerated()pada tipe koleksi untuk mendapatkan referensi ke objek (atau tipe nilai) dalam koleksi, serta indeksnya:

[1,2,3,4,5].enumerated().forEach{print($0,$1)}

atau

for (c,i) in [1,2,3,4,5].enumerated(){print(c,i)}

atau ( CountableClosedRangesintaks lebih pendek )

(1...5).enumerated().forEach{print($0,$1)}

Cetakan:

0 1
1 2
2 3
3 4
4 5
JAL
sumber
2

Substring

Kadang-kadang, Anda dapat menyimpan byte dengan jatuh kembali ke tipe Foundation daripada menggunakan tipe Swift murni. Bandingkan mengakses substring dari NSStringvs Stringtipe Swift :

let x:NSString = "hello world"
x.substringToIndex(5) // "hello"

let y = "hello world"
y.substringToIndex(y.startIndex.advancedBy(5)) // "hello"

Bahkan dengan 9 karakter yang hilang dengan mendeklarasikan xsebagai NSString, Anda menyimpan 25 lebih banyak dengan menggunakan tipe Foundation, karena substringToIndexmengambil sebagai Intsebagai parameter untuk NSString, vs sebuah Indexstruct ( String.CharacterView.Index) untuk Stringtipe Swift .

Saya harus mencatat bahwa ketersediaan tipe Foundation mungkin berbeda di beberapa platform (OS X, Linux, dll). Sebagian besar kelas Foundation NSUnimplementeddalam versi open-source dari Swift.

JAL
sumber
2

.peta()

Menggabungkan .map()dengan sintaks trailing closure dapat memperketat for-loop. Kita bisa meletakkan hal-hal yang ingin kita iterate ke dalam array, lalu gunakan .map()untuk melakukan beberapa tindakan pada setiap elemen.

Sebagai contoh, kita dapat menggunakannya .map()untuk menulis berangan tua itu, Fizzbuzz, dalam satu baris.

var d: [Int] = Array(1...100)

d.map{$0%15 == 0 ? print("Fizzbuzz") : $0%3 == 0 ? print("Fizz") : $0%5 == 0 ? print("Buzz") : print($0)}

Di luar golf, .map()dapat membantu mengurangi pengulangan. Sebagai contoh, misalkan Anda memiliki pandangan yang Anda butuhkan untuk memposisikan secara terprogram. Anda dapat menempatkan jangkar untuk tampilan ke dalam array anonim dan menjalankannya .map()untuk mengatur setiap kendala .isActivemenjadi benar, seperti:

_ = [
        view.topAnchor.constraint(equalTo: view.topAnchor, constant: 40),
        view.widthAnchor.constraint(equalTo: view.widthAnchor),
        view.centerXAnchor.constraint(equalTo: view.centerXAnchor),
        view.bottomAnchor.constraint(equalTo: view.bottomAnchor)
    ].map { $0.isActive = true }
Martyav
sumber
1
Bukankah lebih baik menggunakan forEachcontoh kedua Anda? mapharus benar-benar digunakan untuk mengubah konten array, dan bukan sebagai pintasan iterasi. Dalam hal ini, Anda membuang hasilnya.
JAL
1

Penempatan variabel golf dalam struktur aliran kontrol menggunakan tupel

Pertimbangkan Anda ingin menggunakan whileloop, dan Anda ingin menggunakan hal yang sama di kedua kondisi dan blok untuk diikuti. Kemudian, penugasan sebaris dalam tuple kemungkinan besar akan membantu. Semakin lama atribut Anda, semakin baik! Pertimbangkan ini (lebih pendek 3 byte):

func f(s:[Int]){var k=s,i=0;while(i=k.count,i>0).1{print(i,i+k[i-1]);k.removeLast();}}

lebih dari ini:

func g(s:[Int]){var k=s,i=0;while k.count>0{i=k.count;print(i,i+k[i-1]);k.removeLast();}}

Perhatikan (i=k.count,i>0).1bagian yang cukup menarik.


Terinspirasi oleh salah satu jawaban Herman Lauenstein .

Tuan Xcoder
sumber
1

String berulang

Sayangnya, Swift tidak mendukung perkalian String dengan *, juga Python. Metode yang baik yang bisa Anda gunakan adalah String(repeating:count:), tetapi sayangnya itu tidak terlalu golf. Bandingkan dua pendekatan ini:

var a=String(repeating:"abc",count:3)

dan

var a="";for _ in 0..<3{a+="abc"}

Yang kedua adalah beberapa byte lebih pendek, tetapi itu tidak dapat digunakan dalam penutupan ... Lebih baik lagi, dan itu juga bekerja dalam penutupan:

(0..<3).map{_ in"abc"}.joined()

Dan bagaimana jika saya melakukannya berkali-kali? Nah, Anda bisa menggunakannya String.init(). Sekarang, ini dapat menghemat banyak byte. Misalnya (68 byte):

let k=String.init(repeating:count:)
print(k("abcd",9)+k("XYZxyz",9))

alih-alih (74 byte):

print(String(repeating:"abcd",count:9)+String(repeating:"XYZxyz",count:9))

atau (70 byte):

var f={String(repeating:$0,count:$1)}
print(f("abcd",9)+f("XYZxyz",9))

Tapi pastikan String Anda cukup panjang. Jika Anda menggunakan String(repeating:"abc",3), lebih baik menggunakan "abcabcabc"saja.

Tuan Xcoder
sumber
1 karena saya tidak punya variabel ide bisa menjadi inisialisasi seperti itu.
Daniel
1

Impor

Anda dapat mengganti import Foundationdengan import UIKituntuk 5 byte lebih pendek, karena UIKit sudah mengimpor Yayasan.

Cur
sumber
1
Ah kamu benar. Tidak melihat itu di ulasan
mbomb007