Как кодировать Fizzbuzz в F #

У ImprovedNamingStrategy есть метод addUnderscores (), который вызывается из tableName () и columnName (), вы можете реализовать свой собственный класс стратегии именования и переопределить их согласно вашему выбору

    public class MyOwnNamingStrategy extends ImprovedNamingStrategy {
        @Override
        public String tableName(String tableName) {
        //return addUnderscores(columnName); // skip this
        return columnName; // if you want column name variable name same
        //return changeAsYouWant(columnName); // as name sames
       }
   }
23
задан Russell 11 March 2010 в 05:15
поделиться

7 ответов

Я думаю, что у вас уже есть "лучшее" решение.

Если вы хотите продемонстрировать больше функциональных/F#-измов, вы можете сделать, например,

[1..100] 
|> Seq.map (function
    | x when x%5=0 && x%3=0 -> "FizzBuzz"
    | x when x%3=0 -> "Fizz"
    | x when x%5=0 -> "Buzz"
    | x -> string x)
|> Seq.iter (printfn "%s")

и использовать списки, последовательности, map, iter, паттерны и частичное применение.

[1..100]    // I am the list of numbers 1-100.  
            // F# has immutable singly-linked lists.
            // List literals use square brackets.

|>          // I am the pipeline operator.  
            // "x |> f" is just another way to write "f x".
            // It is a common idiom to "pipe" data through
            // a bunch of transformative functions.

   Seq.map  // "Seq" means "sequence", in F# such sequences
            // are just another name for IEnumerable<T>.
            // "map" is a function in the "Seq" module that
            // applies a function to every element of a 
            // sequence, returning a new sequence of results.

           (function    // The function keyword is one way to
                        // write a lambda, it means the same
                        // thing as "fun z -> match z with".
                        // "fun" starts a lambda.
                        // "match expr with" starts a pattern
                        // match, that then has |cases.

    | x when x%5=0 && x%3=0 
            // I'm a pattern.  The pattern is "x", which is 
            // just an identifier pattern that matches any
            // value and binds the name (x) to that value.
            // The "when" clause is a guard - the pattern
            // will only match if the guard predicate is true.

                            -> "FizzBuzz"
                // After each pattern is "-> expr" which is 
                // the thing evaluated if the pattern matches.
                // If this pattern matches, we return that 
                // string literal "FizzBuzz".

    | x when x%3=0 -> "Fizz"
            // Patterns are evaluated in order, just like
            // if...elif...elif...else, which is why we did 
            // the 'divisble-by-both' check first.

    | x when x%5=0 -> "Buzz"
    | x -> string x)
            // "string" is a function that converts its argument
            // to a string.  F# is statically-typed, so all the 
            // patterns have to evaluate to the same type, so the
            // return value of the map call can be e.g. an
            // IEnumerable<string> (aka seq<string>).

|>          // Another pipeline; pipe the prior sequence into...

   Seq.iter // iter applies a function to every element of a 
            // sequence, but the function should return "unit"
            // (like "void"), and iter itself returns unit.
            // Whereas sequences are lazy, "iter" will "force"
            // the sequence since it needs to apply the function
            // to each element only for its effects.

            (printfn "%s")
            // F# has type-safe printing; printfn "%s" expr
            // requires expr to have type string.  Usual kind of
            // %d for integers, etc.  Here we have partially 
            // applied printfn, it's a function still expecting 
            // the string, so this is a one-argument function 
            // that is appropriate to hand to iter.  Hurrah!
53
ответ дан 29 November 2019 в 00:37
поделиться

Чтобы добавить еще один возможный ответ - вот еще один подход без сопоставления с образцом. Он использует тот факт, что Fizz + Buzz = FizzBuzz, поэтому вам не нужно проверять все три случая, вам нужно только посмотреть, делится ли оно на 3 (затем вывести «Fizz»), а также посмотреть, делится ли оно на 5 (затем выведите «Buzz») и, наконец, выведите новую строку:

for i in 1..100 do
  for divisor, str in [ (3, "Fizz"); (5; "Buzz") ] do
    if i % divisor = 0 then printf str
  printfn ""

Вложенный цикл for присваивает 3 и «Fizz» значение divisor и str в первой итерации, а затем вторая пара значений во второй итерации. Преимущество заключается в том, что вы можете легко добавить печать "Jezz", когда значение делится на 7 :-) ... в случае, если проблема заключается в расширяемости решения!

10
ответ дан Tomas Petricek 11 March 2010 в 05:15
поделиться

Вот моя версия:

//initialize array a with values from 1 to 100
let a = Array.init 100 (fun x -> x + 1)

//iterate over array and match *indexes* x
Array.iter (fun x ->
    match x with
        | _ when x % 15 = 0 -> printfn "FizzBuzz"
        | _ when x % 5 = 0 -> printfn "Buzz"
        | _ when x % 3 = 0 -> printfn "Fizz"
        | _ -> printfn "%d" x
) a

Это моя первая программа на F #.

Это не идеально, но я думаю, что тот, кто начинает изучать F # (как я :)), может понять, что здесь происходит довольно быстро.

Однако мне интересно, в чем разница между соответствием любому _ или самому x в сопоставлении с образцом выше?

1
ответ дан Grzegorz Gierlik 11 March 2010 в 05:15
поделиться

Я не смог найти работающее решение, которое не включало бы тестирование для i% 15 = 0 . Я всегда чувствовал, что не тестирование для этого является частью этого "глупого" задания. Имейте в виду, что это, вероятно, не идиоматический F #, так как это моя первая программа на языке.

for n in 1..100 do 
  let s = seq { 
    if n % 3 = 0 then yield "Fizz"
    if n % 5 = 0 then yield "Buzz" } 
  if Seq.isEmpty s then printf "%d"n
  printfn "%s"(s |> String.concat "")
1
ответ дан Jonas Elfström 11 March 2010 в 05:15
поделиться

Мне не нравятся все эти повторяющиеся строки, вот моя:

open System
let ar = [| "Fizz"; "Buzz"; |]
[1..100] |> List.map (fun i ->
    match i % 3 = 0, i % 5 = 0 with
        | true, false ->  ar.[0]
        | false, true ->  ar.[1] 
        | true, true ->  ar |> String.Concat
        | _ -> string i
    |> printf "%s\n"
)
|> ignore
0
ответ дан Graham 11 March 2010 в 05:15
поделиться

Еще одно решение в стиле F # (т.е. с использованием активных шаблонов):

let (|P3|_|) i = if i % 3 = 0 then Some i else None
let (|P5|_|) i = if i % 5 = 0 then Some i else None

let f = function
  | P3 _ & P5 _ -> printfn "FizzBuzz"
  | P3 _        -> printfn "Fizz"
  | P5 _        -> printfn "Buzz"
  | x           -> printfn "%d" x

Seq.iter f {1..100}
//or
for i in 1..100 do f i
12
ответ дан 29 November 2019 в 00:37
поделиться

Мой пример - лишь незначительное улучшение по сравнению с кодом, опубликованным ssp. Он использует параметризованные активные шаблоны (которые принимают делитель в качестве аргумента). Вот более подробное объяснение:

Следующее определяет активный шаблон , который мы позже можем использовать в выражении match , чтобы проверить, имеет ли значение i делится на значение делитель . Когда мы пишем:

match 9 with
| DivisibleBy 3 -> ...

... это означает, что значение «9» будет передано следующей функции как i , а значение 3 будет передано как делитель . Имя (| DivisibleBy | _ |) - это специальный синтаксис, означающий, что мы объявляем активный шаблон (и имя может появиться в совпадении в левой части -> .Бит | _ | означает, что шаблон может завершиться ошибкой (наш пример терпит неудачу, когда значение не делится на делитель )

let (|DivisibleBy|_|) divisor i = 

  // If the value is divisible, then we return 'Some()' which
  // represents that the active pattern succeeds - the '()' notation
  // means that we don't return any value from the pattern (if we
  // returned for example 'Some(i/divisor)' the use would be:
  //     match 6 with 
  //     | DivisibleBy 3 res -> .. (res would be asigned value 2)
  // None means that pattern failed and that the next clause should 
  // be tried (by the match expression)
  if i % divisor = 0 then Some () else None 

Теперь мы можем перебрать все числа и сопоставить их шаблоны (наш активный шаблон) с использованием match (или с использованием Seq.iter или какой-либо другой техники, как показано в других ответах):

for i in 1..100 do
  match i with
  // & allows us to run more than one pattern on the argument 'i'
  // so this calls 'DivisibleBy 3 i' and 'DivisibleBy 5 i' and it
  // succeeds (and runs the body) only if both of them return 'Some()'
  | DivisibleBy 3 & DivisibleBy 5 -> printfn "FizzBuzz"
  | DivisibleBy 3 -> printfn "Fizz" 
  | DivisibleBy 5 -> printfn "Buzz" 
  | _ -> printfn "%d" i

Для получения дополнительной информации об активных шаблонах F #, вот ссылка на документацию MSDN . Думаю, если убрать все комментарии, код будет чуть читабельнее, чем исходная версия. Здесь показаны довольно полезные приемы :-), но в вашем случае задача относительно проста ...

24
ответ дан 29 November 2019 в 00:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: