ドワーフとコイン


32

状況:

数人のMドワーフがゴブリンの胸にN金貨を見つけ、それらを分割しなければなりません。海賊への略奪品の優先順位の割り当てを管理する古代のルールにより、最古のドワーフは次の最古のドワーフよりもコインを1つ多く獲得する必要がありM-1ます。さらに、小人はコインを投げる必要はありません(つまり、小人に負のコインはありません)

ドワーフがこのようにコインを分割するのを手伝うか、これが不可能であることを伝えてください。

勝者のコードは常に正しく答える必要があり(この課題は決定論的)、一般的な規則に従う必要があります。

入力

コインの数には整数N(3≤N≤1000)が与えられ、スペースで区切られたドワーフの数には整数M(3≤M≤N)が与えられます。

出力

ドワーフが望むようにコインを分割できない場合は、-1(マイナス1)を印刷します。そうでない場合は、各ドワーフが受け取るコインの数を、最古から最年少まで印刷します。数字はスペースで区切ります。

サンプル

入力

3 3

出力

2 1 0

入力

9 3

出力

4 3 2

入力

7 3

出力

-1

入力

6 4

出力

3 2 1 0

4
「海賊」を見逃しました。
ローリング14


3
良い発見、@ Raystafarian。そのソルバはJ.している場合は特に-教師はMのための一般的な解法は、ドワーフの代わりに、わずか3なった場合、おそらく、S /彼は:)ユーザーが答えをクラウドソーシングことを認識するだろう
ProgrammerDan

宿題かどうか、それはスマーフの良い質問です!
レベルリバーセント14

回答:


18

J- 32 29 28 25

ない 他のJソリューションよりも短い、 しかし そして、異なるアイデアを使用します

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

最高ランクのgnomeが獲得しているコインの数に対する答えは、単純にN/M+(M-1)/2(整数の場合)、これの否定を構築し-:@-.@]-%ます。次に、引数のi:ような配列を作成し、そこからM個の要素を取得します。2 1 0 _1 _2_2


1
+1の素晴らしい使用法i:。あなたは書き込むことによって、他の3つの文字を保存することができます%代わりに[%]、そして使用して-.@]の代わりに(1-])
algorithmshark 14

@algorithmshark仲間のJ愛好家に感謝します!
スウィッシュ

1
@swishは私たちが奪ったばかりのノームと一緒にいるようで、+ 1できません。;)
TheConstructor 14

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=.+/&-各引数(&)で上記のアクションを実行+/し、これらの配列から追加テーブル()を作成します。これで、各行がM個のドワーフにコインを分配できるテーブルができましたが、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

入力で9 34 3 2なくが返され-1ます。あなたの例の使用法に転位があるようです?
ProgrammerDan 14

@ProgrammerDanありがとう、それを理解できませんでした。間違った例を入力しました。9 3gives 4 3 27 3gives _1、期待どおり。
algorithmshark 14

修正を見て、適切に+1しました:D。Jを調べる必要があります。気の利いたようです。
ProgrammerDan 14

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)

ゴルフをしていない:

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がd星の数である場合、支払われた金のシーケンスは2つの特異なシリーズに分解できます。最初にゼロで終わるシリーズ: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

-1、質問では関数ではなく完全なプログラムを記述する必要があります。参照してくださいmeta.codegolf.stackexchange.com/a/1146/8766
user80551

@ user80551そのとおりです。スニペットを修正しました。スペースで区切られた入力を受け取ります。出力には「[1]」も表示されなくなりました。
lambruscoAcido

1
次の文字に置き換えm*(m+1)/2て別のキャラクターを保存できますsum(1:m)
ブライアンディグス14

@Brian Thx、コードを修正します!
lambruscoAcido

4

PHP(187)

それはゴルフの私の最初の試みであり、私はそれが良いかもしれないことを知っていますが、それでも:)

ゴルフ:

<?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');}?>

ゴルフをしていない:

<?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

Python 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)

ヘッドアップをありがとう。入力要件にスペース区切りが追加されていることに気付きませんでした。
ジオビット14

これらは100文字かもしれませんが、ギリシャ語の変数名のため、105バイトが必要です。
ジョナサンフレッチ

4

Pythonの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. elseの後および ''の前のスペースを削除します。1文字
  2. スペースでの分割がデフォルトであるため、split()内の ''を削除します。3文字
  3. divmod内で-1から+1を変更してxを1下げ、次に範囲関数を変更して範囲の逆順オプションを使用します。3文字。
  4. 編集:... if ... else ...が...および...または... 2文字に変更されました。
  5. 編集:Divmodは明示的に、rは削除されました。4文字。
  6. 編集:xが削除され、m // nが明示的に使用されました。1文字
  7. 編集: '' .join(map(str、...))の代わりにスター付きの式を使用し、print()の繰り返しを避けるためにxを追加しました。12文字。
  8. 編集:負の数のコインをドワーフに与えることを許可していることに気付きました。これを避けるためにコードを変更しました。

よくやった、それは有益だった:)私は不必要なスペースを取り除くために私の答えを変えたが、保存するあなたのトリック[::-1]は私のソリューションよりも優れている。+1
Evpok 14

私は何かが欠けていることかもしれないが、私は93バイトの代わりに、94カウント
ジョナサンFRECHを

3

Python 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

Python 2のprintステートメントスタイルをサポートするPython 3バージョンはありましたか?または、最後の行(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);}}

2
PPCGへようこそ、削除できる空白がたくさんあるようです。
pastebin.comスラッシュ0mr8spkT

より多くのスペースを取り除いて、あなたの答えをもう少しゴルフすることができます-たとえば、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に向かうベクトルを作成し、合計がNを下回らなくなるまで各数値に1を加算します。それが優れている場合は、-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

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

ほんの少しの代数で、本来あるべきよりもずっと長くかかった。


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

を使用c=consolec.log()て短縮できます。
user2428118 14

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つの整数、コイン、ドワーフを読み取ります。
ドワーフごとの差を減算します。
残りのmod dwarves> 0の場合、不可能です。
それ以外の場合、dwarves-1〜0のループでドワーフごとに等しいシェアを取得し、dwarfIndex + equal shareを出力します。

非ゴルフ

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までの1ずつ増加するすべてのシーケンスを生成し、それらの合計が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


1

C 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);}

非ゴルフ

#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にはタイプがないため、これは警告付きでコンパイルされます。これがゴルフのルールで有効でない場合は、5人のキャラクターを追加する必要があります。


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

受け取り入力して格納しようab

        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総要求お金が総使用可能なお金と等しいかどうかによって



-1

Python(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]

ゴルフをしていない:

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]

2
これは、入力要件に従っていません。
オースティンヘンリー14

-1、質問は関数ではなく完全なプログラムを書く必要があります。見るmeta.codegolf.stackexchange.com/a/1146/8766
user80551
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.