Я читал о выражениях условного стиля в рубине. Однако я наткнулся на одну, которую не мог понять, чтобы определить классическую проблему FizzBuzz. Я понимаю проблему FizzBuzz и даже написал свою, прежде чем нашел следующее быстрое решение с использованием тернарного оператора. Если бы кто-нибудь мог объяснить мне, как работает эта цепочка для решения проблемы FizzBuzz, я был бы очень признателен :)
for i in 0...100
puts i%3==0 ? i%5==0 ? "FizzBuzz" : "Buzz" : i%5==0 ? "Fizz" : i
end

Некоторые скобки могут помочь:
puts (i%3 == 0) ? ((i%5 == 0) ? "FizzBuzz" : "Buzz") : ((i%5 == 0) ? "Fizz" : i)
Итак, если i делится на 3, тогда он проверяет, делится ли i также на 5. Если да, то выводит «FizzBuzz», иначе просто «Buzz». Если i не делится на три, тогда он снова проверяет делимость на 5 и печатает «Fizz», если так, в противном случае просто i.
поток:
if (i%3 == 0) { // multiple of 3
if (i%5 == 0) { // multiple of 3 and 5
puts "FizzBuzz"
} else { // not multiple of 5, only of 3
puts "Buzz"
}
} else ( // not multiple of 3
if (i%5 == 0) { // multiple of 5, not of 3
puts "Fizz"
} else { // multiple of neither 5 nor 3
puts i
}
}
Тернар - это базовая структура «если-то».
Вышеупомянутое эквивалентно ...
if i%3 ==0
if i%5 == 0
"FizzBuzz"
else
"Buzz"
else
if i%5 == 0
"Fizz"
else
i
Или, используя пару скобок ...
puts i%3==0 ? ( i%5==0 ? "FizzBuzz" : "Buzz" ) : ( i%5==0 ? "Fizz" : i )
Извиняюсь. Я просто ленился.
Вот описание проблемы FizzBuzz, как указано в этом Статья Джеффа Этвуда.
Write a program that prints the numbers from 1 to 100. But for multiples of three print "Fizz" instead of the number and for the multiples of five print "Buzz". For numbers which are multiples of both three and five print "FizzBuzz".
тернарный оператор - это сокращенная запись для оператора if-else. Общий формат:
cond ? evaluate_if_cond_is_true : evaluate_if_cond_is_false
Итак, если я напишу:
int isEven = (i % 2 == 0) ? 1 : 0;
Эквивалентен следующему коду:
if (i % 2 == 0) {
isEven = 1;
} else {
isEven = 0;
}
Где cond - это i % 2 == 0, Assessment_if_cond_is_true - это 1, а Assessment_if_cond_is_false - это 0.
В тернарных операторах хорошо то, что их можно комбинировать. Это означает, что оператор, выполняемый, когда одно из условий оценивается как истинное или ложное, может быть другим тернарным оператором.
Давайте представим все условие в более удобочитаемом виде:
i%3==0 ?
i%5==0 ?
"FizzBuzz"
: "Buzz"
: i%5==0 ?
"Fizz"
: i
И сопоставить это с операторами if-else легко с помощью правил, описанных выше:
if (i%3==0) {
if (i%5==0) {
"FizzBuzz"
} else {
"Buzz"
}
} else {
if (i%5==0) {
"Fizz"
} else {
i
}
}
Это недопустимый код, но поскольку результат тернарного оператора встроен в выражение результата, он используется в качестве входных данных для команды put.
Ради интереса вот еще один способ:
puts (1..100).map {|i| (fb = [["Fizz"][i%3],["Buzz"][i%5]].compact.join).empty? ? i : fb}
И другой:
(1..100).zip([nil,nil,"Fizz"]*34,[nil,nil,nil,nil,"Buzz"]*20).map {|a,b,c| b || c ? [b,c].join : a}
Это не правильно. В спецификации указано, что вы должны печатать номер только в том случае, если вы не печатаете шипение или жужжание.
Просто для развлечения. Если вы хотите сделать это на C#. Вот простой способ. Он в основном начинается с вашего цикла for, который будет печатать числа от 1 до 100. Затем он спрашивает, делится ли ваш индекс «i» на 3 и 5, если он истинен, а затем выводит на консоль «FizzBuzz». В противном случае, если ваш индекс «i» делится на 3, если true, то выведите в консоль «Fizz». Иначе, если ваш индекс «i» делится на 5, если true, то выведите в консоль «Buzz». В противном случае просто распечатайте «i», которое является вашим целым числом. Я добавил табуляцию для лучшей читаемости.
for(int i = 1; i <= 100; i++) {
string result = (i % 3 == 0 && i % 5 == 0) ?
"FizzBuzz" :
(i % 3 == 0) ?
"Fizz" :
(i % 5 == 0) ?
"Buzz" :
i.ToString();
Console.WriteLine(result);
}
Большое спасибо - скобки и ваше объяснение помогли решить эту проблему.