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


21

Какие общие советы у вас есть для игры в гольф в F #? Я ищу идеи, которые могут быть применены к кодовым проблемам гольфа в целом, которые, по крайней мере, несколько специфичны для F # (например, «удалить комментарии» - это не ответ). Пожалуйста, оставьте один совет за ответ.

Ответы:


9

Используйте functionвместо того, matchкогда это возможно; он сохранит 6 символов для 1-символьных переменных:

let f=function // ... (14 chars)

против

let f x=match x with // ... (20 chars)

Он также может заменить любое сопоставление с образцом, чтобы последовательно сохранить 1 символ:

match a with|          // ... (13 chars)
a|>function|           // ... (12 chars)
(function| (* ... *))a // (12 chars)

8

Нужно использовать метод для переменной, для которого вы еще не ограничили тип? Просто сравните его с литералом того типа, который вам нужен, а затем отбросьте результат, чтобы аннотировать тип этой переменной:

let f (x:string)=x.Length
let f x=x="";x.Length

7

По возможности используйте префиксную нотацию для инфиксных операторов - это избавит вас от необходимости определять функцию для их использования.

Например, вы можете включить это:

List.map(fun i->i+2)[1;1;2;3;5;8]

в это:

List.map((+)2)[1;1;2;3;5;8]

1
Я использую это здесь, спасибо!
Aloisdg говорит восстановить Monica

5

Деконструкция кортежей

Если вы не можете обойтись при использовании переменных, используйте деконструкцию кортежа вместо нескольких выражений let

let a,b ="",[]

вместо того

let a=""
let b=[]

Чтение со стандартного ввода

Библиотека ядра F # определяет псевдоним для System.Console.Inвызываемого stdin. Это позволяет вам читать ввод.

// Signature:
stdin<'T> :  TextReader

TextReader на MSDN

Большим преимуществом является тот факт, что он короче, чем Consoleвам, и вам не нужно открывать систему.

Перебор строки

Строка в основном char seq, это позволяет вам использовать Seq.mapнапрямую со строками. Также возможно использовать их в понимании[for c in "" do]

Mutables / Reference клетки

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

Общие советы

  • Можно написать полный match .. withтекст

    function|'a'->()|'b'->()|_->()
    
  • Нет необходимости в пробелах до и после не буквенно-цифровых символов.

    String.replicate 42" "
    if Seq.exists((<>)'@')s then
    if(Seq.exists((<>)'@')s)then
    
  • Если вам нужно заполнить строку слева или справа пробелами, вы можете использовать для этого флаги [s] printf [n].

    > sprintf "%20s" "Hello, World!";;
    val it : string = "       Hello, World!"
    

    Модуль Core.Printf



3

Эта-конвертация для функций

Большое спасибо Лайкони за этот совет в одном из моих решений .

Рассмотрим функцию, скажем, для суммирования строки с 3 для заглавных букв и 1 для всех остальных символов. Так:

let counter input = Seq.sumBy (fun x -> if Char.IsUpper x then 3 else 1) input

По эте-преобразование , это может быть переписано как:

let counter = Seq.sumBy (fun x -> if Char.IsUpper x then 3 else 1)

и вызывается так же, как и раньше:

counter "Hello world!" |> printfn "%i"

Функция оператора прямого сложения >>

Теперь предположим, что наша первоначальная задача состоит в суммировании строки с 3 для букв верхнего регистра и 1 для букв нижнего регистра, а все остальные символы исключаются.

Мы могли бы написать это как:

let counter input = Seq.filter Char.IsLetter input |> Seq.sumBy (fun x -> if Char.IsUpper x then 3 else 1)

Мы можем использовать оператор прямой композиции ( >>), чтобы связать две функции ( Seq.filterи Seq.sumBy) вместе. С eta-преобразованием определение функции стало бы:

let counter = Seq.filter Char.IsLetter >> Seq.sumBy (fun x -> if Char.IsUpper x then 3 else 1)

Крис Смит написал отличную статью об >>операторе в своем блоге MSDN .


2

По возможности Seqкороче чем List:

[[1];[2;3];[4];[5]|>List.collect
[[1];[2;3];[4];[5]|>Seq.collect

на один символ короче ...


2

Избегайте скобок при использовании одного параметра и в кортеже

let f = [(0,1);(1,4)]|>Seq.map(fst)
printfn "%A" f

можно написать

let f = [0,1;1,4]|>Seq.map fst
printfn "%A" f

1
Вам также не нужно () обходить кортежи: let f = [0,1; 1,4] |> Seq.map fst
thinkbeforecoding

1
Спасибо. обновлено.
Aloisdg говорит восстановить Монику

2

Предпочитать новую строку строки над "\ n"

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

(18 байт)

string.Concat"\n"

(17 байт)

string.Concat"
"

Вдохновленный ответом Chiru для es6 .

Используется здесь



1

Используйте лямбды, чтобы сохранить байт. Например, это:

let f x=x*x

Можно выразить так:

fun x->x*x


1

moduleКлючевое слово может быть использовано для сокращения имен модулей при использовании повторно. Например:

Array.fold ...
Seq.iter ...
List.map ...

может стать

module A=Array
A.fold ...
module S=Seq
S.iter ...
module L=List
L.map ...

Это более полезно для более длинных программ, где методы модуля используются многократно (и каждый раз должны иметь полное имя, потому что они имеют RequireQualifiedAccessмодификатор), и позволяют сбрасывать несколько символов, особенно когда более полезно использовать обычный массив CLR (например, изменяемость ), чем F # seqили list.

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