Гномы и Монеты

32

Ситуация:

Несколько ( M) гномов нашли сундук гоблина с Nзолотыми монетами и должны их разделить. Из-за древних правил, регулирующих распределение добычи у пиратов в порядке старшинства, самый старый гном должен получить на одну монету больше, чем следующий самый старый гном, и так далее, чтобы у самого молодого гнома было M-1меньше монет, чем у самого старого гнома. Кроме того, ни один гном не должен вносить какие-либо монеты (т. Е. Никакие отрицательные монеты ни одному гному)

Помогите гномам разделить монеты таким образом или скажите им, что это невозможно.

Код победителя должен всегда отвечать правильно (этот вызов является детерминированным) и следовать общим правилам .

вход

Вам дается целое число N (3 ≤ N ≤ 1000) для количества монет и целое число M (3 ≤ M ≤ N) для количества дварфов, разделенных пробелом.

Выход

Если невозможно разделить монеты так, как этого хотят гномы, выведите -1 (минус одна). В противном случае выведите номера монет, которые получит каждый гном, от самой старой до самой молодой. Разделите числа пробелами.

Образцы :

вход

3 3

выход

2 1 0

вход

9 3

выход

4 3 2

вход

7 3

выход

-1

вход

6 4

выход

3 2 1 0
Томас Мортелл
источник
4
Вы пропустили "пират".
Роулинг
6
актуально
Raystafarian
3
Хорошая находка, @Raystafarian. Возможно, когда учитель получит общий решатель для M дварфов вместо 3, он / она узнает, что пользователь краудсорсировал ответ :) - особенно если этот решатель находится в J.
ProgrammerDan
Домашняя работа или нет, это хороший вопрос Smurfing!
Уровень реки St

Ответы:

18

J - 32 29 28 25

Не короче, чем другое решение J, но и использует другую идею

(]{.[:i:-:@-.@]-%)/ ::_1:

Ответ на количество монет, которые получает гном самого высокого ранга, прост N/M+(M-1)/2(если это целое число), мы строим отрицание этого -:@-.@]-%. Затем i:создает массив 2 1 0 _1 _2для аргумента, _2и мы берем из него М элементов.

рассекать
источник
1
+1 за блестящее использование i:. Вы можете сохранить еще три символа, написав %вместо [%]и используя -.@]вместо (1-]).
алгоритмистика
@algorithmshark Спасибо товарищ J энтузиаст!
swish
1
Не могу +1, как @swish, кажется, с гномами, которых мы только что ограбили. ;)
TheConstructor
11

J - 30 символов

Очень весело в гольф. Многое получилось аккуратно.

((+/@s~i.[){ ::_1:s=.+/&i.&-)/

Объяснение:

  • /- Возьмите разделенные пробелом целые числа в качестве аргумента и вставьте функцию между ними. То есть рассмотрим N левый аргумент функции в скобках (...)и M правый аргумент.

  • i.&-- Отрицать ( -), а затем взять целые числа ( i.). Обычно, когда вы делаете что-то подобное, i.5вы получаете 0 1 2 3 4. Однако, когда i.получает отрицательное число, он переворачивает этот список вывода. Так, например i._5, даст 4 3 2 1 0.

  • s=.+/&- Выполните указанное выше действие для каждого аргумента ( &), а затем создайте таблицу сложений ( +/) из этих массивов. Теперь у нас есть таблица, в которой каждая строка является возможным распределением монет среди дварфов, хотя, возможно, нет, когда есть N монет. Наконец, этот глагол создания таблиц настолько полезен, что мы назовем его sи будем использовать позже.

  • +/@s~- Теперь мы sснова используем , но поменяем местами ( ~) порядок аргументов, чтобы мы транспонировали таблицу. Это простой способ получения суммы каждой строки после создания таблицы ( +/@), связанный с тем, как J суммирует многомерные списки.

  • i.[ - В этом списке сумм мы ищем левый аргумент для глагола, т. Е. N. Если N - элемент, мы получаем этот индекс: иначе мы получаем длину списка, который, в частности, является недопустимым индексом.

  • { ::_1:- Теперь мы пытаемся использовать индекс, чтобы вытащить строку из таблицы в s. {выдаст ошибку домена, если индекс недействителен, поэтому в этом случае мы ловим ошибку ( ::) и возвращаем -1 ( _1:). Это обрабатывает все. Поскольку мы используем i.&-ранее, распределение монет будет в порядке убывания, как было необходимо.

Использование:

   ((+/@s~i.[){ ::_1:s=.+/&i.&-)/ 9 3
4 3 2
   ((+/@s~i.[){ ::_1:s=.+/&i.&-)/ 7 3
_1
   ((+/@s~i.[){ ::_1:s=.+/&i.&-)/ 6 4
3 2 1 0
   ((+/@s~i.[){ ::_1:s=.+/&i.&-)/ 204 17
20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4
algorithmshark
источник
Вход 9 3должен вернуться 4 3 2, а не -1. Кажется, в вашем примере используется транспозиция?
ProgrammerDan
@ProgrammerDan Спасибо, не понял этого. Я напечатал примеры неправильно. 9 3дает 4 3 2и 7 3дает _1, как и ожидалось.
алгоритмшарк
Увидел исправление и +1 соответственно: D. Я должен смотреть в J, выглядит изящно.
ProgrammerDan
7

R - 71 70 67 66 65 символов

s=scan();m=s[2];x=s[1]-sum(1:m);cat(if(x%%m|-m>x)-1 else x/m+m:1)

Ungolfed:

s = scan()    # Reads N and M by stdin.
m = s[2]
x = s[1] - m*(m-1)/2
cat(if (x %% m | x < -m) -1 else x/m + m:1)

Решение:

Если M число карликов, то последовательность платного золота можно разложить на две особые серии. Сначала серия, заканчивающаяся нулем: M-1, ..., 2, 1, 0 и постоянная серия c, c, ..., c. Сумма первой серии всегда M * (M-1) / 2. Таким образом, если остаток (x = N - M * (M-1) / 2) можно разделить без остатка (по модулю, равному 0), каждый карлик получает x / M плюс часть убывающего ряда.

Использование:

> s=scan()
1: 10 4
3: 
Read 2 items
> m=s[2]
> x = s[1] - m*(m-1)/2
> cat(if (x %% m || x<0) -1 else x/m + (m-1):0)
4 3 2 1
lambruscoAcido
источник
-1, вопрос требует написания полной программы, а не функции. См. Meta.codegolf.stackexchange.com/a/1146/8766
user80551
@ user80551 Вы правы. Теперь я исправил фрагмент: теперь он принимает разделенный пробелами ввод; вывод также больше не показывает '[1]'.
lambruscoAcido
1
Вы можете сохранить другого персонажа, заменив его m*(m+1)/2наsum(1:m)
Брайан Диггс
@Brian Thx, я изменю свой код!
lambruscoAcido
4

PHP (187)

Это моя первая попытка игры в гольф, и я знаю, что это может быть лучше, но все же :)

Golfed:

<?php
$b=fgets(STDIN);list($c,$d)=explode(' ',$b);if((($d&1)AND($c%$d==0))OR($c%$d==$d/2)){for($e=floor($c/$d)+floor($d/2);$e>floor($c/$d)-round($d/2);$e--){echo"$e ";}}else{die('-1');}?>

Ungolfed:

<?php
$a = fgets(STDIN);
list($coins, $dwarves) = explode(' ', $a);
if ((($dwarves & 1) AND ($coins % $dwarves == 0)) OR ($coins % $dwarves == $dwarves / 2)) {
    for (
        $i = floor($coins / $dwarves) + floor($dwarves / 2);
        $i > floor($coins / $dwarves) - round($dwarves / 2);
        $i--
    ) {
        echo "$i ";
    }
}
else { 
  die('-1');
}
?>

Выполнить в оболочке

Основная идея:

Монеты могут быть разделены по этим правилам, если одно из них верно:

  1. Гномы имеют нечетное число, а монеты делятся на гномов без остатка
  2. Гномы чётные, а количество монет, оставшихся после деления монет / гномов, равно половине числа гномов.

Если это так, мы берем за основу среднее количество монет на гнома (ACPD). Но мы должны начинать с самого высокого и выходить, пока не достигнем самого низкого. Таким образом, мы делаем цикл со счетчиком, начинающимся с ACPD + счетчик остальных гномов к верхнему концу, и продолжаем, пока не достигнем ACPD - счетчик остальных гномов к нижнему концу.

Это в основном то же самое, если дварфы странные (то есть 5 дварфов - средний - 3, и на обоих концах осталось 2), но не если они четные - именно поэтому мы полагаемся на пол И раунд.

Проблемы на данный момент: Работает со слишком низким количеством монет, что означает, что некоторые гномы будут избиты и лишены своего драгоценного заработка. И это грустно. Или, по крайней мере, если вы любите гномов.

Решение :

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

Более разумное решение :

Монеты металлические. Заставьте гномов расплавить их всех, а затем бросьте их в меньшем / большем количестве монет, чтобы они были делимы в любом случае.

Самое умное решение :

Укради их гору, переименуй себя в Смауг и сохрани все это для себя. В конце концов, почему вы должны беспокоиться о сварливых гномах?

Северный мост
источник
4

Питон 3 (100)

Использование той же идеи, что и @Geobits, но в соответствии с требованиями ввода и вывода.

n,m=map(int,input().split())
κ,ρ=divmod(n-m*(m-1)//2,m)
x=[-1]if ρ else range(κ,κ+m)[::-1]
print(*x)
Evpok
источник
Спасибо за хедз-ап. Не заметил разделения пространства, добавленного к входным запросам.
Geobits
Это может быть 100 символов, но из-за имен греческих переменных требуется 105 байтов.
Джонатан Фрех,
4

Питон 3 - 109 107 103 102 90 93

Используя ту же идею, что и Evpok, но с рядом улучшений.

n,m=map(int,input().split())
k=n/m+m/2
a=int(k)
print(*(range(a,a-m,-1),[-1])[k-a-.5or~a>-m])

Улучшения:

  1. Устранение пространства после еще и до ''. 1 персонаж
  2. Устранение '' внутри функции split (), потому что разделение на пробелы используется по умолчанию. 3 персонажа
  3. Уменьшение x на 1 изменяет значение от -1 до +1 внутри divmod, а затем изменяет функцию диапазона, чтобы использовать опцию обратного порядка диапазона. 3 персонажа.
  4. РЕДАКТИРОВАТЬ: ... если ... еще ... изменилось на ... и ... или ... 2 символа.
  5. РЕДАКТИРОВАТЬ: Divmod сделал явным, r удален. 4 персонажа.
  6. РЕДАКТИРОВАТЬ: x удалено, m // n используется явно. 1 персонаж
  7. РЕДАКТИРОВАТЬ: использовал помеченные выражения вместо '' .join (map (str, ...)), добавил x, чтобы избежать повторения print (). 12 символов.
  8. РЕДАКТИРОВАТЬ: Я понял, что я позволял гномам давать отрицательное количество монет. Я изменил код, чтобы избежать этого.
isaacg
источник
Отлично, это было поучительно :) Я изменил свой ответ, чтобы убрать лишнее пространство, но твой трюк для экономии [::-1]лучше моего решения. +1
Евпок
Я могу что-то упустить, но я насчитал 93 байта вместо 94.
Джонатан Фрех,
3

Питон 3 - 114

n,m=map(int,input().split(' '))
r=range(m);n-=sum(r)
if n%m<1:
 for x in r:print(m-x+n//m-1,end=' ')
else:print -1

Работает, проверяя, N-(M*(M-1)/2)делится ли на M. Новое в python, поэтому любые советы приветствуются.

Пример Ideone.com

Input:
735 30
Output:
39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10
Geobits
источник
Была ли когда-либо версия Python 3, которая поддерживала printстиль выражения Python 2 ? Или как последняя строка ( else:print -1) не приводит к ошибке?
Джонатан Фрех,
3

C # - 322

using System;using System.Linq;namespace D{class P{static void Main(string[]args){int n=Convert.ToInt16(args[0]);int m=Convert.ToInt16(args[1]);bool b=false;int q=n/2+1;g:b=!b;int[]z=new int[m];for(int i=0;i<m;i++){z[i]=q-i;}if(z.Sum()==n)foreach(int p in z)Console.Write(p+" ");else{q--;if(b)goto g;Console.Write(-1);}}}}

Ужасная оценка, но я выбрал другой подход и начал использовать goto:)

Я сокращу это позже.

Остин Хенли
источник
1
Вы можете определенно сократить все эти Convert.ToInt16звонки до просто int.Parse. Вы можете объявить любую предварительно назначенную переменную с помощью var(вместо, например, int[]). Ваши параметры командной строки не нужно вызывать args. И вы можете псевдоним часто используемых типов, как using C = Console. Я также думаю, что для такого решения лучше представить интервал без изменений, а не сохранять только пару символов. О, и я не совсем уверен, почему gotoздесь лучше, чем альтернативы ...
Aaronaught
3

Java 210

class A { public static void main(String[] a){int d=Integer.parseInt(a[0]),c=Integer.parseInt(a[1]);if (2*c%d==0) for (int i=0;i<d;i++) System.out.print((((1+(2*c/d)-d)/2)+i)+" "); else System.out.print(-1);}}
user902383
источник
2
Добро пожаловать в PPCG, я вижу, у вас много пробелов, которые можно удалить.
user12205
Вы можете выделить намного больше места для того, чтобы отыграть свой ответ немного дальше - например, class A{public static void main(String[]a)он действителен и экономит 3 символа. После каждого ifи вокруг каждого forудаляйте пробелы ... и т. Д.
ProgrammerDan
Это безумие, что часть public static void main (S) такая же длинная, как и все J-решение :)
Роберт Грант,
3

R: 77 73 70 символов

a=scan();r=a[2]:1-1;while((n=sum(r))<a[1])r=r+1;cat(`if`(n>a[1],-1,r))

Создайте вектор, идущий от (M-1) до 0, и добавляйте 1 к каждому числу, пока сумма не перестанет уступать N. Если она выше, выведите -1, иначе выведите вектор.

С отступом и немного безголовый:

a=scan()   #Reads in stdin (by default numeric, space-separated)
r=a[2]:1-1 #Creates vector (M-1) to 0
while(sum(r)<a[1])r=r+1 #Increments all member of vector by 1 until sum is not inferior to N
cat( #Outputs to stdout
    `if`(sum(r)>a[1], -1, r) #If superior to N: impossible, returns -1
    )

Пример использования:

> a=scan();r=a[2]:1-1;while((n=sum(r))<a[1])r=r+1;cat(`if`(n>a[1],-1,r))
1: 9 3
3: 
Read 2 items
4 3 2
> a=scan();r=a[2]:1-1;while((n=sum(r))<a[1])r=r+1;cat(`if`(n>a[1],-1,r))
1: 7 3
3: 
Read 2 items
-1
> a=scan();r=a[2]:1-1;while((n=sum(r))<a[1])r=r+1;cat(`if`(n>a[1],-1,r))
1: 204 17
3: 
Read 2 items
20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4
plannapus
источник
2

Юлия, 45

f(n,m)=(x=n/m-m/2+1/2;x%1==0?[x+m-1:-1:x]:-1)
julia> f(6,4)'
1x4 Array{Float64,2}:
 3.0  2.0  1.0  0.0

Просто немного алгебры, заняло у меня намного больше времени, чем следовало.

GGGG
источник
2

JavaScript - 76

Заметьте, что k + (k - 1) + ... + (k - (M - 1)) = M (k - (M - 1) / 2). Если установить это значение равным N, то k = N / M + (M -1) / 2 для наибольшей суммы. Если это целое число, то k% 1 == 0, а суммы, которые мы ищем, равны k, k - 1, ..., k - (M - 1).

Я мог бы написать это короче на другом языке, но еще не было решения JS, так что вот оно:

N=3;M=3;if((r=N/M+(M-1)/2)%1)console.log(-1);else while(M--)console.log(r--)

Запустите в консоли.

Пример ввода:

N=3;M=3;if((r=N/M+(M-1)/2)%1)console.log(-1);else while(M--)console.log(r--)

Выход:

3
2
1 

Входные данные:

N=6;M=4;if((r=N/M+(M-1)/2)%1)console.log(-1);else while(M--)console.log(r--)

Выход:

3
2
1
0

Входные данные:

N=7;M=3;if((r=N/M+(M-1)/2)%1)console.log(-1);else while(M--)console.log(r--)

Выход: -1

Жаль, что console.log так долго пишется :) К сожалению, объявление l=console.log.bind(console)не делает его короче и просто l=console.logне работает.

Входные данные:

"N=3;M=3;if((r=N/M+(M-1)/2)%1)console.log(-1);else while(M--)console.log(r--)".length

Выход:

76
CompuChip
источник
Вы можете использовать c=consoleи c.log()сократить его.
user2428118
2

Golfscript, 35

~:M.(*2/-.M%{;-1}{M/M+,-1%M<' '*}if

Как это работает

В следующем примере ввод 9 3.

          # STACK: "9 3"
~         # Interpret the input string.
          # STACK: 9 3
:M        # Store the top of the stack (number of dwarves) in variable `M'.
.         # Duplicate the top of the stack.
          # STACK: 9 3 3
(         # Decrement the top of the stack.
          # STACK: 9 3 2
*         # Multiply the topmost elements of the stack.
          # STACK: 9 6
2/        # Divide the top of the stack by `2'.
          # STACK: 9 3
          # So far, we've transformed `M' into `M*(M-1)/2', which is the minimum amount of
          # coins all dwarves together will get. This number comes from the fact that the
          # youngest dwarf will get at least 0 coins, the next at least 1 coin, etc., and
          # 0 + 1 + ... + (M - 1) = M*(M-1)/2.
-         # Subtract the topmost elements of the stack.
          # STACK: 6
          # The remaining coins have to get reparted evenly to all dwarves.
.         # Duplicate the top of the stack.
          # STACK: 6 6
M%        # Calculate the top of the stack modulus `M'.
          # STACK: 6 0
{         # If the modulus is positive, the remaining coins cannot get reparted evenly.
    ;-1   # Replace the top of the stack by `-1'.
}
{         # If the modulus is zero, the remaining coins can get reparted evenly.
    M/    # Divide the top of the stack by `M'.
          # STACK: 2
          # This is the number of coins all dwarves will get after giving 1 to the second
          # youngest, etc.
    M+    # Add `M' to the top of the stack.
          # STACK: 5
    ,     # Replace the top of the stack by an array of that many elements.
          # STACK: [ 0 1 2 3 4 ]
          # The rightmost element is the number of coins the oldest dwarf will get.
    -1%   # Reverse the array.
          # STACK: [ 4 3 2 1 0 ]
    M<    # Keep the leftmost `M' elements.
          # STACK: [ 4 3 2 ]
          # There are only `M' dwarves.
    ' '*  # Join the array, separating by spaces.
          # STACK: "4 3 2"
}if
Деннис
источник
1

Delphi XE3 (176)

uses SysUtils;var d,c,i:integer;begin read(c,d);for I:=1to d-1do c:=c-i;if c mod d>0then writeln(-1)else begin c:=c div d;for I:=d-1downto 0do write(IntToStr(i+c)+' ');end;end.

Как это работает.

Читает 2 целых числа, монеты и гномы.
Вычитает разницу на карлика.
Если оставшийся мод гномов> 0, это невозможно.
Иначе получить равную долю за дварфа в цикле дварфов-1 до 0 и печатает dwarfIndex + равную долю

Ungolfed

uses SysUtils;
var
  d,c,i:integer;
begin
  read(c,d);
  for I:=1to d-1do
    c:=c-i;
  if c mod d>0then
    writeln(-1)
  else
  begin
    c:=c div d;
    for I:=d-1downto 0do
      write(IntToStr(i+c)+' ');
  end;
end.
Теун Пронк
источник
1

Mathematica 65

Функция, g генерирует все увеличивающиеся на единицу последовательности длиной m от 0 до n и проверяет, суммирует ли любая из них m. В случае успеха последовательность возвращается; в противном случае возвращается -1.

Последовательности сделаны Partition включения списка {0,1,2,3… m} во все возможные подсписки из n смежных целых чисел.

Есть, конечно, более эффективные способы достижения того же эффекта, но те, которые я нашел, требуют больше кода.

n_~g~m_:=If[(s=Select[Partition[0~Range~n,m,1],Tr@#==n&])=={},-1,s]

Примеры

g[9, 3]

{{2, 3, 4}}


g[3, 3]

{{0, 1, 2}}


g[7, 3]

-1


g[705, 3]

{{234, 235, 236}}


g[840, 16]

{{45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60}}


g[839, 16]

-1

DavidC
источник
1

С 131

#include <edk.h>
main(int a,char **v){int j=atoi(*++v),k=atoi(*++v)-j*(j-1)/2;k<0||k%j?j=1,k=-1:k/=j;while(j--)printf("%d ",k+j);}

Ungolfed

#include <edk.h> //Shortest standard header including stdio.h and stdlib.h
main(int a,char **v)
{
    int j=atoi(*++v),k=atoi(*++v)-j*(j-1)/2;

    k<0||k%j?j=1,k=-1:k/=j;  // If youngest dwarf gets < 0 or amount not equally divisible then set values such that ...

    while(j--)printf("%d ",k+j); // ... loop prints out correct values
}

Это компилируется с предупреждением, потому что main не имеет типа. Если это не действует в правилах игры в гольф, мне нужно добавить пять символов.

Alchymist
источник
1

Кобра - 198

Сайт Кобры

class P
    def main
        x,y=Console.readLine.split
        a,b=x to int,y to int
        l=[]
        t=n=0
        for i in b,t+=i
        while (t+=b)<=a,n+=1
        for i in b,l.insert(0,i+n)
        print if(t-b<>a,-1,l.join(" "))

Разъяснение:

class P
    def main

Требуется для запуска кода

        x,y=Console.readLine.split
        a,b=x to int,y to int

Принимает ввод и сохраняет его как aиb

        l=[]
        t=n=0

Инициализирует список вывода lи инициализирует общее количество денег tи количество монет, которые нужно добавить в каждую стопку гномов.n

        for i in b,t+=i

Находит минимально возможную ценность денег, в результате чего у всех дварфов будет допустимое количество монет в их стопке

        while (t+=b)<=a,n+=1

Определяет, сколько монет добавить в каждую стопку, чтобы общая требуемая сумма была> = к общей сумме доступных денег.

        for i in b,l.insert(0,i+n)

Заполняет список кучами денег разных размеров

        print if(t-b<>a,-1,l.join(" "))

Выходы либо -1или в lзависимости является ли общие требуемыми деньги равны общей доступной цена

Οurous
источник
-1

Питон ( 100 96 94):

Хороший, зачетный ответ. Не больше, но теперь оно короче.

def f(n,m):a=range(m)[::-1];b=n-sum(a);c=b/m;d=[i+c for i in a];return(d,-1)[-1in d or c*m!=b]

Ungolfed:

def f(n,m):
 a = range(m)[::-1]
 b = sum(a)
 c = (n-b)/m
 if c * m != n-b: return -1
 d = [i+c for i in a]
 return (d,-1)[-1 in d or c!=n-b]
 if -d in d or c*m!=n-b:
  return -1
 return d

Выход:

def f(n,m):a=range(m)[::-1];b=sum(a);c=(n-b)/m;d=[i+c for i in a];return (d,-1)[-1 in d or c*m!=n-b]

f(3,3)
Out[2]: [2, 1, 0]

f(9,3)
Out[3]: [4, 3, 2]

f(7,3)
Out[4]: -1

f(6,4)
Out[5]: [3, 2, 1, 0]
ɐɔıʇǝɥʇuʎs
источник
2
Это не соответствует входным требованиям.
Остин Хенли
-1, вопрос требует написания полной программы, а не функции. См. Meta.codegolf.stackexchange.com/a/1146/8766
user80551