Советы по игре в гольф в Swift


24

Какие советы по игре в коде в Swift? Акцент на безопасности, кажется, затрудняет игру в гольф, но это делает маленькие советы и даже более полезными. Существуют ли какие-либо функции в Swift, которые могут помочь ему в определенных видах применения в код-гольфе?

Пожалуйста, оставьте один совет за ответ.


11
Вы можете рассчитывать на нас - если это должно быть безопасно, это сделают d̶a̶n̶g̶e̶r̶o̶u̶s̶ гольфом!
Конор О'Брайен

9
Надеюсь, что некоторые хорошие советы приходят быстро.
DJMcMayhem

4
Свифт в гольф? Я думал, что гольф должен был быть медленной, спокойной игрой ...
Jojodmo

Ответы:


6

Изменяется

Одна вещь, которая действительно полезна - это создание диапазонов с помощью операторов ...или..<

Например

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

Итак, чтобы получить значения со 2 по 4 массива

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

Практическое использование

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

С помощью

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

На 8 байт короче

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

4
... for n in 0...3{print(a[n])}не действует?
Джулиан Вольф

4

Затворы:

Использование переменных, удерживающих функцию, против использования самой функции может помочь:

65 байт:

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

66 байт:

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

Небольшая разница здесь, но она покажет больше в некоторых головоломках.

Укорочение функции:

Глядя на предыдущий пример напоминает мне кое-что. Иногда, если вы будете использовать функцию достаточно много раз, стоит переименовать ее:

Это:

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

К этому:

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

Или, собственно, так лучше:

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

Таким образом, вы просто звоните r("Hello World",8)вместоString(repeating:"Hello World",count:8)

Оставляя объявления типов:

Однажды я создал замыкание, не задав тип аргумента, и таким образом создал более короткий ответ:

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

Компилятор сделал вывод, что iв Int.

Создать массивы быстрый путь:

Если вам нужен массив Ints, используйте Rangeдля его создания:

Array(0...5)

Это делает то же самое, что и:

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

Массивы вместо Ifили Switch:

Вместо этого:

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

Вы, вероятно, можете сделать это:

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

Укороченные типы:

Если вы часто используете преобразование типов, вы можете создать псевдоним типа:

typealias f=Float

Карта:

Помните, что вам часто не нужно использовать returnключевое слово в mapфункции.

Запуск Swift Online:

Хотя Try It Online не поддерживает Swift, он делает это сейчас !


2
Спасибо за пост. Мне очень помогло. tio.run/nexus теперь работает со swift :)
palme

3

try

В Swift 2.x и выше функции, которые традиционно обрабатывали ошибки, передавая указатель на NSErrorобъект в качестве параметра функции, теперь являются throwих ошибкой.

Это означает, что это:

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

теперь выглядит так:

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

Это можно сократить с помощью try?или try!. try?оценит выражение, nilесли возникнет ошибка. try!вылетит из программы, если возникнет ошибка, и ее следует использовать только в тех случаях, когда ошибка не возникнет.

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

try?и try!сохранить как минимум 13 байтов из do-try-catchцикла. Обратите внимание, что вы также сохраняете по крайней мере еще один байт, передавая пустой массив ( []) для параметров, nilа не также.


3

Сокращение Массивов

Итерирование с for-in loopsпомощью массива для получения одного значения, такого как сумма элементов внутри или произведение его элементов, может быть слишком длинным для того, насколько это просто на самом деле. Вы можете просто использовать reduce()метод. Некоторые примеры:

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

Добавление элементов в массив с помощью for-inциклов:

var sum = 0

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

можно упростить до:

print(array.reduce(0, +))

И получить произведение элементов внутри массива с помощью циклов for-in:

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

также может быть уменьшен до:

print(array.reduce(1, *))

Не теряете ли вы больше байтов, объявляя **функцию, чем просто вызывая powвручную?
JAL

@JAL да, но если вы вызываете pow 10 раз, это экономит небольшое количество байтов. Не самая лучшая техника игры в гольф, но это еще одна потенциальная помощь. Он не был предназначен специально для pow, но для других операций, таких как поиск простых чисел, если вы сделаете это 3 раза, это сэкономит огромное количество байтов
Mr. Xcoder

2

Тернарный оператор Свифта очень лаконичен: condition ? action : otherдействие

Если условие истинно, сделай одно, если нет, то сделай другое.

textColor = bgIsBlack ? .white : .black

Это делает textColorбелый, если фон черный, или черный, если фон любого другого цвета.

Оператор слияния ноль еще короче: a ?? b

Допустим, вы проверяете JSON для определенного ключа, чтобы вы могли представить значение ключа в виде текста заголовка. Если ключ отсутствует (то есть значение равно nil), мы хотим дать заголовок текст по умолчанию.

title = keysValue ?? "Not Available"

2

перечисление

Вы можете цепь forEachиз enumerated()по типу коллекции , чтобы получить ссылку на объект (или тип значения) в коллекции, а также его индекс:

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

или

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

или (даже более короткий CountableClosedRangeсинтаксис)

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

Печать:

0 1
1 2
2 3
3 4
4 5

2

Substring

Иногда вы можете сохранять байты, обращаясь к типам Foundation вместо использования чистых типов Swift. Сравните доступ к подстроке NSStringс Stringтипом Swift :

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

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

Даже с 9 символов , потерянных объявляя xкак NSString, вы экономите более 25 с помощью типа Foundation, так как substringToIndexпринимает в Intкачестве параметра NSString, по сравнению с Indexструктурой ( String.CharacterView.Index) для Swift Stringтипов.

Следует отметить, что доступность типов Foundation может различаться на разных платформах (OS X, Linux и т. Д.). Большинство базовых классов находятся NSUnimplementedв версии Swift с открытым исходным кодом.


2

.карта()

Сочетание .map()с конечным синтаксисом замыкания может затянуть циклы for. Мы можем поместить вещи, которые мы хотим перебрать в массив, а затем использовать .map()для выполнения некоторых действий с каждым элементом.

Например, мы можем использовать .map()этот старый каштан Fizzbuzz в одну строку.

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

Вне гольфа, .map()может помочь сократить количество повторений. Например, предположим, что у вас есть представление, которое вам нужно позиционировать программно. Вы можете поместить якоря для представления в анонимный массив и запустить .map()его, чтобы установить для каждого ограничения .isActiveзначение true, например, так:

_ = [
        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
Не лучше ли использовать forEachво втором примере? mapдействительно должен использоваться для преобразования содержимого массива, а не как ярлык итерации. В этом случае вы отбрасываете результат.
JAL

1

Назначение переменных для игры в гольф в структурах потока управления с использованием кортежей

Предположим, вы хотите использовать whileцикл, и вы хотите использовать одну и ту же вещь как в условии, так и в последующем блоке. Тогда, скорее всего, поможет встроенное назначение в кортеже. Чем дольше ваш атрибут, тем лучше! Учтите это (на 3 байта короче):

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

через это:

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

Обратите внимание на ту (i=k.count,i>0).1часть, которая довольно интересна.


Вдохновленный одним из ответов Германа Лауэнштейна .


1

Повторяющиеся строки

К сожалению, Swift не поддерживает умножение строк с помощью *Python. Хороший метод, который вы можете использовать вместо этого String(repeating:count:), но, к сожалению, это не совсем гольф. Сравните эти два подхода:

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

а также

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

Второй - на пару байтов короче, но его нельзя использовать в замыкании ... Еще лучше, и он также работает в замыканиях:

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

А что если я сделаю это несколько раз? Ну, вы можете использовать String.init(). Теперь это может сэкономить много байтов. Например (68 байт):

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

вместо (74 байта):

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

или (70 байт):

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

Но убедитесь, что ваша строка достаточно длинная. Если вы используете String(repeating:"abc",3), гораздо лучше использовать "abcabcabc"вместо этого.


+1, потому что я понятия не имел, что переменные могут быть инициализаторами, как это.
Даниэль

1

импорт

Вы можете заменить import Foundationс import UIKitна 5 байт короче, так как UIKit делает импорт Foundation уже.


1
Ах, ты прав. Не видел этого в обзоре
mbomb007
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.