Wskazówki do gry w golfa w Swift


24

Jakie są wskazówki dotyczące gry w golfa w Swift? Koncentracja na bezpieczeństwie wydaje się utrudniać grę w golfa, ale to czyni małe wskazówki, a nawet bardziej przydatne. Czy w Swift są jakieś funkcje, które mogą pomóc w osiągnięciu doskonałości w grze w golfa w niektórych aplikacjach?

Proszę zamieścić jedną wskazówkę na odpowiedź.


11
Możesz na nas liczyć - jeśli ma to być bezpieczne, zostanie zrobione d̶a̶n̶g̶e̶r̶o̶u̶s̶ golfy!
Conor O'Brien

9
Mam nadzieję, że szybko pojawi się kilka dobrych wskazówek.
DJMcMayhem

4
Szybkie golfa? Myślałem, że golf powinien być powolną, spokojną grą ...
Jojodmo

Odpowiedzi:


6

Zakresy

Jedną z rzeczy, która jest naprawdę pomocna, jest tworzenie zakresów za pomocą operatorów ...lub..<

Na przykład

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

Tak więc, aby uzyskać od 2 do 4 wartości tablicy

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

Praktyczne użycie

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

Za pomocą

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

Jest o 8 bajtów krótszy niż

for n in 0...3{let v=a[n];print(v)}

4
for n in 0...3{print(a[n])}Nie jest ważny?
Julian Wolf

4

Zamknięcia:

Zastosowanie zmiennych, które przechowują funkcję w porównaniu z użyciem samej funkcji, może pomóc:

65 bajtów:

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

66 bajtów:

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

Mała różnica tutaj, ale pokaże więcej w niektórych łamigłówkach.

Funkcje skracania:

Spojrzenie na poprzedni przykład przypomina mi coś. Czasami, jeśli będziesz używać funkcji wystarczająco dużo razy, warto zmienić jej nazwę:

To:

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

Do tego:

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

W rzeczywistości jest to lepsze:

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

W ten sposób po prostu dzwonisz r("Hello World",8)zamiastString(repeating:"Hello World",count:8)

Deklaracje typu „Leaving Out”:

Kiedyś utworzyłem zamknięcie bez ustawiania typu argumentu, tworząc krótszą odpowiedź:

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

Kompilator wywnioskował, że ijest w Int.

Twórz tablice w szybki sposób:

Jeśli potrzebujesz tablicy Ints, użyj a, Rangeaby ją utworzyć:

Array(0...5)

To robi to samo, co:

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

Tablice zamiast Iflub Switch:

Zamiast tego:

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

Prawdopodobnie możesz to zrobić:

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

Skróć typy:

Jeśli często korzystasz z konwersji typów, możesz utworzyć alias typu:

typealias f=Float

Mapa:

Pamiętaj, że często nie musisz używać returnsłowa kluczowego w mapfunkcji.

Uruchamianie Swift Online:

Chociaż Try It Online nie obsługuje teraz Swift It !


2
Dzięki za post. Bardzo mi pomogło. tio.run/nexus działa teraz z swift :)
palme

3

try

W Swift 2.xi nowszych funkcje, które tradycyjnie obsługiwały błędy, przekazując wskaźnik do NSErrorobiektu jako parametr funkcji, teraz throwich błąd.

Oznacza to, że to:

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

teraz wygląda następująco:

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

Można to skrócić za pomocą try?lub try!. try?oceni wyrażenie, niljeśli zostanie zgłoszony błąd. try!spowoduje awarię programu, jeśli zostanie zgłoszony błąd, i powinien być używany tylko w przypadkach, w których nigdy nie wystąpi błąd.

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

try?i try!zapisz co najmniej 13 bajtów z do-try-catchpętli. Zauważ, że oszczędzasz również co najmniej jeden bajt, przekazując pustą tablicę ( []) dla opcji zamiast nil.


3

Zmniejszanie tablic

Iteracja for-in loopsza pomocą tablicy w celu uzyskania pojedynczej wartości, takiej jak suma elementów w środku, lub iloczyn jej elementów może być zbyt długi, jak na to w rzeczywistości jest prosty. Możesz po prostu użyć tej reduce()metody. Kilka przykładów:

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

Dodawanie elementów w tablicy za pomocą for-inpętli:

var sum = 0

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

można uprościć:

print(array.reduce(0, +))

I uzyskanie iloczynu elementów wewnątrz tablicy za pomocą pętli for-in:

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

można również zredukować do:

print(array.reduce(1, *))

Czy nie tracisz więcej bajtów, deklarując **funkcję niż po prostu wywołując powręcznie?
JAL

@JAL tak, ale jeśli wywołasz pow 10 razy, oszczędza to niewielką ilość bajtów. Nie do końca najlepsza technika golfowa, ale to tylko kolejna potencjalna pomoc. Nie był przeznaczony specjalnie do pow, ale do innych operacji, takich jak wyszukiwanie liczb pierwszych, jeśli zrobisz to 3 razy, to zaoszczędzi ogromną ilość bajtów
Mr. Xcoder

2

Potrójny operator Swifta jest bardzo zwięzły: condition ? action : otherakcja

Jeśli warunek jest spełniony, zrób jedną rzecz, jeśli nie, zrób coś innego.

textColor = bgIsBlack ? .white : .black

To sprawia, że textColorbiały, jeśli tło jest czarne, lub czarny, jeśli tło ma inny kolor.

Brak koalescencji operatora jest jeszcze krótszy: a ?? b

Załóżmy, że sprawdzasz JSON pod kątem określonego klucza, abyś mógł przedstawić wartość klucza jako tekst tytułu. Jeśli klucz nie jest obecny (tzn. Wartość wynosi zero), chcemy nadać tytułowi domyślny tekst.

title = keysValue ?? "Not Available"

2

Wyliczenie

Możesz utworzyć łańcuch forEachod enumerated()typu kolekcji, aby uzyskać odwołanie do obiektu (lub typu wartości) w kolekcji, a także jej indeks:

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

lub

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

lub (nawet krótsza CountableClosedRangeskładnia)

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

Wydruki:

0 1
1 2
2 3
3 4
4 5

2

Podciąg

Czasami możesz zaoszczędzić bajty, wracając do typów Foundation zamiast używać czystych typów Swift. Porównaj dostęp do podłańcucha typu NSStringSwift vs String:

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

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

Nawet przy 9 znakach utraconych przez zadeklarowanie xjako NSString, oszczędzasz 25 więcej, używając typu Foundation, ponieważ substringToIndexbierze Intjako parametr dla NSStringvs vs. Indexstruct ( String.CharacterView.Index) dla Stringtypów Swift .

Powinienem zauważyć, że dostępność typów Fundacji może być różna na różnych platformach (OS X, Linux itp.). Większość klas Foundation odbywa się NSUnimplementedw otwartej wersji Swift.


2

.mapa()

Połączenie .map()ze składnią końcowego zamykania może zaostrzyć pętle for. Możemy umieścić rzeczy, które chcemy iterować, w tablicy, a następnie użyć .map()do wykonania akcji na każdym elemencie.

Na przykład możemy użyć .map()tego starego kasztana, Fizzbuzz, w jednym wierszu.

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)}

Poza golfem .map()może pomóc ograniczyć powtarzalność. Załóżmy na przykład, że masz widok, który musisz pozycjonować programowo. Możesz umieścić zakotwiczenia widoku w anonimowej tablicy i przejechać .map()je, aby ustawić .isActiveprawdziwe ograniczenia dla każdego z nich :

_ = [
        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 }

1
Czy nie jest lepiej używać forEachw drugim przykładzie? mappowinien być naprawdę używany do przekształcania zawartości tablicy, a nie jako skrót iteracyjny. W takim przypadku odrzucasz wynik.
JAL

1

Przydziały zmiennych golfowych w kontrolnych strukturach przepływu za pomocą krotek

Rozważ, że chcesz użyć whilepętli i chcesz użyć tej samej rzeczy zarówno w warunku, jak i bloku do naśladowania. Następnie przyporządkowanie liniowe w krotce najprawdopodobniej pomoże. Im dłuższy atrybut, tym lepiej! Rozważ to (3 bajty krócej):

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

Nad tym:

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

Zwróć uwagę na (i=k.count,i>0).1część, która jest dość interesująca.


Zainspirowana Hermana Lauenstein za odpowiedzi .


1

Powtarzanie ciągów

Niestety, Swift nie obsługuje mnożenia ciągów znaków *, podobnie jak Python. Dobrą metodą, której możesz użyć zamiast tego, jest String(repeating:count:), ale niestety tak naprawdę nie jest golfowa. Porównaj te dwa podejścia:

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

i

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

Drugi jest o kilka bajtów krótszy, ale nie można go użyć w zamknięciu ... Jeszcze lepiej, i działa również w zamknięciach:

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

A jeśli zrobię to wiele razy? Cóż, możesz użyć String.init(). Teraz może to zaoszczędzić wiele bajtów. Na przykład (68 bajtów):

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

zamiast (74 bajtów):

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

lub (70 bajtów):

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

Ale upewnij się, że Twój ciąg jest wystarczająco długi. Jeśli używasz String(repeating:"abc",3), znacznie lepiej jest użyć "abcabcabc"zamiast tego.


+1, ponieważ nie miałem pojęcia, że ​​zmienne mogą być takimi inicjalizatorami.
Daniel

1

Import

Możesz zamienić na import Foundationo import UIKit5 bajtów krótszy, ponieważ UIKit już importuje Foundation.


1
Ach masz rację. Nie widziałem tego w recenzji
mbomb007
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.