トロールの通行料を計算して安全に通過する


12

/puzzling//q/626に触発された


あなたの冒険では、あなたが渡らなければならない一連の7つの橋に到着します。各橋の下にはトロルが住んでいます。橋を渡るには、最初にトロールにいくつかのケーキを運んでいるケーキの数の割合として与える必要があります。これらは親切なトロルであるため、一定数のケーキをあなたに返します。

毎日の初めに、地元のトロール王は、各旅行者が支払う必要のあるケーキ税の割合と、トロールケーキの払い戻し-各トロールが旅行者に返さなければならないケーキの数を設定します。

あなたの仕事は、その日に与えられた条件で7つのトロル橋すべてを通過するために必要なケーキの最小数を計算することです。

仮定:

  1. 2つの入力パラメータ:ケーキ税率(0〜100の整数)、およびトロールケーキの払い戻し。
  2. 誰も、トロルでさえ、ケーキを別のトロルに部分的に食べて欲しくない。ケーキの一部が残っている場合、トロールはそれを取得します。
  3. トロルがケーキ税を受け入れても、すべてのケーキを返さなければならない場合(以前と同じか少ないケーキが残っている)、怒ってあなたとあなたのケーキを食べます。
  4. すべてのトロールは、少なくとも1つの完全なケーキを保持する必要があります。
  5. 最大100個のケーキしか持てません。
  6. あなたが現在いる、または7つの橋すべての反対側にいる日を終わらせる必要があります。

チャレンジ:

現在の日に移動するケーキの最小数を出力する完全なプログラムを作成するか、今日安全に移動できない場合はゼロを出力します。明日の数字がわかるまでお待ちください。

入力は、stdin、コマンドライン引数、またはファイル入力として渡す必要があります。

最短のコード(バイトカウント)が優先されます。

例:

25%のケーキ税、2トロールケーキの払い戻し。


トロール1の前に19個のケーキから開始:
トロール1の後の(19 * 0.75)= 14.25 :(14 + 2)= 16

トロール2の前:(16 * 0.75)= 12
トロール2の後:(12 + 2)= 14

等

19ケーキ-> 16-> 14-> 12-> 11-> 10-> 9-> 8
18ケーキ-> 15-> 13-> 11-> 10-> 9-> 8-> 8(ルール3)

18個のケーキの場合、最後のトロールはケーキを保持できません。したがって、25%/ 2日のケーキの最小数は19です。

input: 25 2
output: 19

例2:

90%のケーキ税、1トロルケーキの払い戻し

100ケーキ-> 11-> 2-> 1(ルール4)

3番目のトロールはケーキを保持できませんでした。そのため、最大数のケーキで始めても90%/ 1日で旅行することはできません。

input: 90 1
output: 0

データ

入力値と出力値の簡単なグラフをまとめます。私はこれが「滑らか」ではないことに驚きました(ベルカーブなど)。いくつかの顕著な島があります。

データチャート

興味がある人のためのデータ。列は5%の間隔に分割され、行は1ケーキの払い戻し間隔の単位です(画像を回転して表示)。28ケーキを超える払い戻しはできないことがわかります。

27, 17, 13, 14, 15, 18, 20, 24, 53, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
47, 27, 20, 19, 19, 19, 24, 39, 48, 68, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0
67, 37, 28, 24, 23, 28, 27, 29, 50, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
87, 47, 33, 29, 27, 28, 31, 44, 37, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 57, 40, 34, 31, 29, 34, 34, 62, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 67, 48, 39, 35, 38, 37, 49, 57, 76, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 77, 53, 44, 39, 38, 47, 39, 59, 78, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 87, 60, 49, 43, 39, 40, 54, 46, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 97, 68, 54, 47, 48, 44, 44, 71, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 73, 59, 51, 48, 47, 59, 73, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 80, 64, 55, 49, 51, 49, 68, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 88, 69, 59, 58, 54, 64, 70, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 93, 74, 63, 58, 57, 54, 57, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 100, 79, 67, 59, 67, 69, 82, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 84, 71, 68, 60, 59, 77, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 89, 75, 68, 64, 74, 79, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 94, 79, 69, 67, 64, 66, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 99, 83, 78, 71, 79, 91, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 87, 78, 74, 69, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 91, 79, 77, 84, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 95, 88, 87, 74, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 99, 88, 80, 89, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 89, 84, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 98, 87, 94, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 98, 91, 84, 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 99, 94, 99, 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 97, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

いい視点ね。簡単にするために完全なプログラムにします。入力は指定できますが、ハードコーディングされていない限り適合とみなされます(更新されたチャレンジ)。

これは、CJamのブルートフォースに適したパズルです。私は明日、その周りをやる

BAH、これは、C#はいいものを持っていることができない理由である

ルール2は、トロールがケーキのごく一部しか受け取らない可能性を排除しているように思われます。しかし、例2では、​​3番目のトロールは0.8ケーキしか得られないと言います。
— デニス14年

仕様に矛盾があります。で25 211ケーキの場合、あなたがトロールに2.75ケーキを与え、トロールは(+。25)0.75を保つように、バック2を取得し、あなたが生き残ります。で90 12ケーキの場合、あなたはトロール1.8を与え、トロールは(+ 2)0.8に保つように、バック1を得るが、あなたは死にます。
— TwiNight 14年

回答:


6

CJam、46 43 41 39 38 36 33バイト

100:H,{)_7{ea:i~H@m2$*H/+@;}*>}#)

ARGVを介した入力。

オンラインインタプリタがありますが、残念ながらコマンドライン引数をサポートしていません。テストのために、このバージョンでSTDINから模倣することができます:

rr]:A;
100:H,{)_7{A:i~H@m2$*H/+@;}*>}#)

ARGVベースのバージョンの説明:

100:H                                  "Push a 100 and save it in H.";
     ,                                 "Create a range (as an array) from 0 to 99.";
      {                       }#       "Find the first index in [0,1,2,...,99] for which the
                                        block produces a truthy (non-zero) value.";
       )_                              "Increment and duplicate the current array element.";
         7{                }*          "Execute the block seven times.";
           ea:i                        "Push the command-line arguments as an array of strings
                                        and convert each element to an integer";
               ~                       "Unwrap the array.";
                H@                     "Push a 100 and rotate the stack to pull up
                                        the first command line argument.";
                  m                    "Subtract (from 100).";
                   2$                  "Copy the last iterations result.";
                     *H/               "Multiply and divide by 100, deducting tax.";
                        +              "Add the refund.";
                         @;            "Rotate top three stack elements, and discard the one that 
                                        has been pulled to the top. This always leaves the last 
                                        two results on the stack.";

                             >         "Make sure that the last result was less than the second 
                                        to last. Yields 0 or 1.";
                                )      "After the # search completes, we'll get -1 if no such 
                                        index exists, or one less than the desired number if it 
                                        does, so we can just increment.";

スタックの内容は、プログラムの最後に自動的に印刷されます。


コードは55 2(の0代わりに100)および56 5(の98代わりに94)に対して誤った結果を生成します。これは、ある100_0.55*-iと25_0.56*-i浮動小数点不正確に落ちる犠牲者。私が知る限り、ペア31 24, 31 25, 33 21, 33 22, 33 23, 35 10, 35 12, 35 15, 35 16, 35 27, 56 1, 57 4も同様に誤った結果を与えます。
— デニス14年

1
@デニス修正、ありがとう!
— マーティンエンダー14年

@Dennisそれは実際にバイトを節約しました。CJamにクロージャーがあれば、税控除を行うブロックを最初に定義し、2つの変数を使用する代わりにそれを使用できます。STDINの代わりにARGVを使用して何かを保存できるかもしれません。
— マーティンエンダー14年

5

CJam、44 40 38 37 35バイト

l~U100:M),{{_M5$-*M/3$+_@<*}7*}=]W=

または、コマンドライン引数と{}#トリックを使用する場合 、33バイト:

100:M,{){_ea:i~M@-@*M/+_@<*}7*}#)

これを私の{}#アプローチとしてメインにしないのは、Martinの答えに触発されたものです。

実行例:

入力:

25 2

出力:

19

別の:

入力:

15 14

出力:

100

使い方

l~                       "Read the two numbers, swap and convert tax to double";
  U100:M),               "Push 0 and [0, 1, ... 100] to stack, storing 100 in M";
          {  ...  }=     "Run this code for each element until top stack element is 1";
           {...}7*       "Run this code block 7 times";
_                        "Copy the array element";
  M5$                    "Push 100 and a copy tax % to stack";
     -*                  "Number = (100 - tax %) * Number";
       M/                "Integer divide the number by 100";          
         3$+             "Add refund";
            _@<*         "Convert to 0 if refunded number > before tax one";
                    ]W=  "Take the last element of the stack";

こちらからオンラインでお試しください


そして今残っているのは、デニスがやって来て私たち二人を打ち負かすのを待つことです。;)
— マーティンエンダー14年

CJamではありません;)(うまくいけば)
— オプティマイザー14年

私はこの]W=トリックが本当に好きですが、今のところ、それを使用しようとするすべての方法で、同じ文字数になります。
— マーティンエンダー14年

@MartinBüttner-ええ、私も。
— オプティマイザー14年

1
@Dennis -今万一作業、2の付加的な利点とは、より短いコードをバイト:D
— オプティマイザ

4

APL(39)

T R←⎕⋄⊃Z/⍨{⍵(⊢×>)R+⌊⍵×1-T÷M}⍣7¨Z←⍳M←100

説明:

  • T R←⎕:キーボードから2つの数字を読み取り、T(税)に保存し、R(return)に。
  • Z←⍳M←100:番号を保存100してM、そしてからのすべての数字1の100中Zます。
  • {... }⍣7¨:の各要素Z、次の関数を7回実行します。
    • R+⌊1-T÷M:支払う必要があるケーキの数を計算し、
    • ⍵(⊢×>):トロルが彼が始めたよりも多くのケーキで終わった場合、その量に1を掛け、そうでなければ0を掛けます。
  • ⊃Z/⍨:の各要素についてZ、その関数が与えた番号でそれを複製します。(したがって、関数が返したすべての数字が0消えます。)そのリストから最初の項目を選択します。リストが空になった場合、これはを与え0ます。

3

C、83バイト

int cake(int perc_taken, int given_back)
{
    int startcake = floor(100.f/perc_taken*given_back+1);
    for(int i = 0; i < 6; i++)
    {
        startcake = ceil((startcake-given_back) * 100.f/(100 - perc_taken));
    }
    return startcake;
}

それが機能する場合、1から100までだけでなく、可能なすべての開始ケーキで機能します。

編集:それは動作します。ゴルフ済み:

n(int p,int g) {int s=100./p*g+1,i=0;for(;i++<6;){s=ceil((s-g)*100./(100-p));}return s;}

「最大100ケーキ」の制限がある場合:

n(int p,int g) {int s=100./p*g+1,i=0;for(;i++<6;){s=ceil((s-g)*100./(100-p));}return s>100?0:s;}

91バイト。


開始時に100個以上のケーキが必要な場合、ソリューションがゼロを返すことは仕様の重要な部分だと思います。
— マーティンエンダー14年


1

C ++-202文字

いつものように、私のC ++は最悪の結果を出しました。

#include<iostream>
int main(){double p,g,c=1,i,r,t;std::cin>>p>>g;for(;c<101;c++){r=c;for(i=0;i<7;i++){t=(int)(r*(1-(p/100))+g);if(t>=r){r=-1;break;}r=t;}if(r!=-1)break;}r!=-1?std::cout<<c:std::cout<<0;}

1

APL、36

x y←⎕⋄101|1⍳⍨y<x×{y+⍵-⌈⍵×x}⍣6⍳x÷←100

説明

「ケーキのしきい値」があることに注意してください。税率xと払い戻しのyためにy÷x、次の橋を通過するにはケーキ以上のものが厳密に必要です。

x y←⎕入力を取得し、x(tax)およびy(return)100で
⍳x÷←100割るに割り当てx、1〜100の配列を生成します。

{y+⍵-⌈⍵×x}⍣6「パスブリッジ」機能を6回呼び出し
⌈⍵×xます。お持ちのケーキの数、倍の税率、切り上げ(お支払い金額)
⍵-お持ちのケーキの数から減算します
y+払い戻し追加

次に、1〜100個のケーキで開始する場合、6つの橋を渡った後に残っているケーキの数を示す100要素の配列を取得します。最後のブリッジを通過できるかどうかを確認するには、しきい値を超えているかどうかを確認しますy÷x。または、次の値よりも大きいかどうか
x×をx
y<チェックして配列を乗算しますy

最後に、
1⍳⍨最初に出現した1(true)のインデックスを見つけ、見つから101なければ
101|mod 101を返します。


1

C 128

他のCソリューションとかなり似ていますが、それは避けられないと思います。主なトリックは、内部ループが完了するかどうかに応じて異なる値で内部ループから抜け出すことです。これにより、?:を使用できます。breakを使用した場合はできませんでした。

t,r,j,k,l,p;main(i){for(scanf("%d%d",&t,&r),i=101;k=--i;){for(j=8;--j>0;)(p=r+k*(100-t)/100)<k?k=p:j=0;j?0:l=i;}printf("%d",l);} 

非ゴルフ

int t,r,j,k,l,p;
main(int i)
{
    for(scanf("%d%d",&t,&r),i=101;k=--i;)
    {
        for(j=8;--j>0;)
        {
            if((p=r+k*(100-t)/100)<k)
                k=p;
            else
                j=0;
        }
        j?0:l=i;
    }
    printf("%d",l);
}

どのコンパイラを使用していますか?
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.