LINUX.ORG.RU

Сумма квадратов двух максимальных чисел

 ,


2

5

Дали задачу на собеседовании, написать в функциональном стиле на скале функцию, которая принимает три целых числа и возвращает для них сумму квадратов двух максимальных чисел. Корявенько получилось придумать такое:

  def twoMaxSquareSum(a: Int, b: Int, c: Int): Int =
    {
      def min(): Int =
        {
          if (a < b && a < c) {
            return a;
          } else if (b < c) {
            return b;
          } else return c;
        }
      def square(x:Int):Int=
      {
        return x*x;
      }
      
      return List(a,b,c).map (square(_)).foldLeft(0)(_ + _)-square(min)
    }
Гуру программирования, как можно сделать красивее? И по-сути не обязательно на скале, решение на других языках тоже с удовольствием гляну

Добавление: А какой вариант вы бы безоговорочно приняли на собеседовании как оптимальный?



Последнее исправление: by_zero (всего исправлений: 1)

Нужно именно красивее? Ну тогда в список, потом sort descending, потом take(2), потом map, потом sum

vertexua ★★★★★
()

sub twomaxum {
    my $sum += $_ * $_ for ( sort {$b <=> $a} @_ )[0, 1];
    return $sum;
}

работает не только с тремя переменными, а вообще с списком чисел. Ограничить количество можно procname($$$).

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от by_zero

Если без списков, то это будет не задача на знание Scala. Действительно, будет что-то на подобии

val min = min(a,min(b,c))

a*a+b*b+c*c-min*min

vertexua ★★★★★
()
class Numeric
	def square
		self**2
	end
end

two_max = -> (x,y,z) { [x,y,z].sort[1..2].map(&:square).inject(:+) }
puts two_max.(1,2,3)

nikolnik ★★★
()

В существующем решении такие недостатки:

  • Непонятно зачем изобреать функцию min, которая и так есть в библиотеке. Тем более не понятно зачем min реализован над тремя параметрами, тогда как остальная логика работает со списками
  • Fold + оператор «жопы» вместо использования стандартной функции sum
  • Складывание трех квадратов и с последующим вычитанием явно лишняя работа
  • Использование List вместо Seq
  • Ключевое слово «return» считается дурным тоном, тем более что тут в нем нет необходимости
  • В функцию map надо передавать напрямую функцию square без лямбды
  • У внутренних функций можно опустить определение типа возвращаемого значения и убрать лишние скобки

В первом приближении все это можно заменить на однострочник:

Seq(1, 2, 3).sorted.drop(1).map(x => x*x).sum
maxcom ★★★★★
()
Ответ на: комментарий от by_zero

1) У коллекций есть

def sorted[B >: A](implicit ord: math.Ordering[B]): List[A].
Используй Ordering

2) Используй sum

3) Вроде просто square или square _ должны работать

vertexua ★★★★★
()

решение на других языках тоже с удовольствием гляну

   a =: +/@:(^&2)@:(0 1 &{)@:({~)\:
   a 6 1 2
40

Вот и подумай, стоит ли вообще писать такие портянки

niemand
()
Ответ на: Haskell от sevenredlines

списки, правда, только трёх элементов.

sevenredlines
()
Ответ на: Clojure от Debasher

Какая она отвратительная!

niemand
()
Ответ на: Haskell от sevenredlines

twoMaxSquareSum xs = sum . map (^2) $ filter (/= minimum xs) xs

Я так и не распарсил. (/= minimum xs). Как я понимаю, частичное применение, да? Непонятно почему не (/= (minimum xs)). А то вроде получается, что первый аргумент /= это minimum, а второй - xs. В общем, Haskell безумно трудный и нелогичный ;)

niemand
()

Я думаю со всеми «красивыми» вариантами что тут привели вас пинком выкинут на улицу, потому что для продакшн кода нужны не умение запихнуть решение в как можно более короткую строку, а читабельность и производительность, именно в таком порядке. Поэтому sort'ам вашим сразу вспомнят оверхед для 3 чисел, а не для трёх - nlogn сложность вместо достаточной тут n. А всему вместе - дикую вырвиглазность (замечу что скаловые варианты читаются не лучше чем перловый). Вариант maxcom'а ещё куда ни шло, хотя там и sort.

На C я бы, наверное, принял без претензий только такой вариант:

int twoMaxSquareSum(int a, int b, int c) {
    if (a <= b && a <= c) 
        return b*b + c*c;
    else if (b <= a && b <= c)
        return a*a + c*c;
    return a*a + b*b;
}   

Функционально уж, я думаю, придумаете как это переписать.

slovazap ★★★★★
()
Ответ на: комментарий от slovazap

Я думаю со всеми «красивыми» вариантами что тут привели вас пинком выкинут на улицу

Ты ошибаешься.

Debasher ★★★★★
()
Ответ на: комментарий от slovazap

На собеседовании был предложен примерно такой вариант. Интересно стало как ещё можно решить эту задачу

by_zero
() автор топика
Ответ на: комментарий от beastie

Там всё просто

@: - это композиция,

& - частичное применение: a&f дает a f x.

({~)\: - это hook. (fg) x= x f (g x)

~ для коммутации. x f~ y = y f x

\: - дает индексы в отсортированном порядке

{ - взятие элементов по индексу(ам)

Но у тебя прям всё очень коротко. Наверное, особая магия

niemand
()
Ответ на: комментарий от slovazap

«Программист на Фортране может написать программу на Фортране на любом языке программирования».

ymn ★★★★★
()
Ответ на: комментарий от slovazap

Просто на C нет всех этих вкусностей. А так уж поверь, кому будет охота читать эти портянки, когда всё можно уложить в 1 строку (если она только не вида %$&^%*%^#*^#*422 3443)

niemand
()
Ответ на: комментарий от slovazap

На C можно и элегантней решить:

#define min(a, b) (*(a) < *(b) ? (a) : (b))
#define min3(a, b, c) (min(a, min(b, c)))

int
sum(int a, int b, int c)
{
        int *p = min3(&a, &b, &c);

        *p = 0;

        return a*a + b*b + c*c;
}
PS: про Фортран выше точно подметили. ;)

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 1)
Ответ на: комментарий от niemand

Но у тебя прям всё очень коротко. Наверное, особая магия

На самом деле просто ренение в лоб. ;) С заду на перёд:

*2 — квадрат

⍵[⍒⍵] — сортируем правый аргумент в обратном порядке (grade down)

2↑ — берём первых 2 элемента (take)

+/ — суммируем

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 1)
Ответ на: комментарий от beastie

Тут даже намёка на элегантность нет. Этот код запутаннее, длиннее и медленнее.

slovazap ★★★★★
()
Ответ на: комментарий от beastie

ох надо же! а define обязательно использовать или его можно легко заменить на функцию? я как-то в этом так и не разобрался...

sevenredlines
()
Ответ на: комментарий от sevenredlines

если я не ошибаюсь, дефайны вроде как быстрее работают

by_zero
() автор топика
def foo(x, y, z):
    return sum(i*i for i in list(sorted((x, y, z)))[1:])

print foo(1, 2, 3)

мой идеальный быдлокод

Virtuos86 ★★★★★
()
Ответ на: Ruby от Kadi

Извините, но что это за херня?!

Virtuos86 ★★★★★
()
Ответ на: комментарий от niemand

Непонятно почему не (/= (minimum xs))

minimum имеет приоритет перед (/=)

но вообще там, кажется, будет правая свертка, то есть функция "(/= minimum)", принимающая xs

Virtuos86 ★★★★★
()
Последнее исправление: Virtuos86 (всего исправлений: 1)

UUUNLIMITED CRAPCODE WORKS!

def do_it(first, second, add_this):
    if first > second:
        return [second, first**2 + add_this]
    else:
        return [first, second**2 + add_this]

a, b, c = 5, 7, 6
print(do_it(a, *do_it(b, c, 0))[1])

Ceiling_QB ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.