คำนวณค่าโทรลล์เพื่อผ่านอย่างปลอดภัย


12

แรงบันดาลใจจาก/puzzling//q/626


ในการผจญภัยของคุณคุณมาถึงสะพาน 7 ชุดที่คุณต้องข้าม ใต้สะพานแต่ละแห่งมีชีวิตอยู่หมุนรอบ ในการข้ามสะพานคุณต้องให้เค้กจำนวนหมุนรอบก่อนเป็นเปอร์เซ็นต์ของจำนวนเค้กที่คุณถือ เพราะนี่เป็นโทรลล์ที่ใจดีพวกเขาจะมอบเค้กให้คุณจำนวนหนึ่ง

ในช่วงเริ่มต้นของแต่ละวันกษัตริย์โทรลล์ท้องถิ่นกำหนดภาษีเค้กร้อยละที่นักท่องเที่ยวแต่ละคนต้องจ่ายและคืนเงินเค้กโทรลล์ - จำนวนเค้กที่แต่ละรอบหมุนรอบจะต้องคืนให้แก่นักเดินทาง

งานของคุณคือการคำนวณจำนวนขั้นต่ำของเค้กที่จำเป็นในการผ่านสะพานหมุนรอบทั้ง 7 อันสำหรับเงื่อนไขที่กำหนดในวันนั้น

สมมติ:

  1. พารามิเตอร์ป้อนเข้าสองรายการ: ภาษีเค้กเปอร์เซนต์ (จำนวนเต็มตั้งแต่ 0 ถึง 100) และการคืนเงินเค้กหมุนรอบ
  2. ไม่มีใครเลยแม้แต่โทรลล์ต้องการเค้กที่กินโดยหมุนรอบอีกบางส่วน หากคุณเหลือเค้กเพียงเล็กน้อย
  3. หากโทรลล์ยอมรับภาษีเค้ก แต่ต้องให้เค้กคืนให้คุณ (เหลือเค้กที่เท่าเดิมหรือน้อยกว่าเดิม) มันจะโกรธและกินคุณและเค้กของคุณ
  4. ทุกรอบหมุนรอบจะต้องเก็บเค้กที่สมบูรณ์ไว้อย่างน้อยหนึ่งก้อน
  5. คุณสามารถพกเค้กได้สูงสุด 100 เค้ก
  6. คุณต้องสิ้นสุดวันที่คุณอยู่ในปัจจุบันหรือที่อีกฝั่งหนึ่งของสะพานทั้ง 7 แห่ง

ท้าทาย:

เขียนโปรแกรมที่สมบูรณ์เพื่อแสดงจำนวนเค้กขั้นต่ำที่จะเดินทางในวันหรือศูนย์ปัจจุบันหากไม่สามารถเดินทางได้อย่างปลอดภัยในวันนี้ - คุณจะรอดูว่าตัวเลขนั้นคืออะไรในวันพรุ่งนี้

อินพุตควรถูกส่งผ่านเป็น stdin, อาร์กิวเมนต์บรรทัดคำสั่งหรืออินพุตไฟล์

รหัสที่สั้นที่สุด (จำนวนไบต์) ชนะ

ตัวอย่าง:

ภาษีเค้ก 25% เค้กคืนเงิน 2 รอบ

เริ่มต้นด้วย 19 เค้ก
ก่อนหมุนรอบ 1: (19 * 0.75) = 14.25
หลังจากหมุนรอบ 1: (14 + 2) = 16

ก่อนหมุนรอบ 2: (16 * 0.75) = 12
หลังจากหมุนรอบ 2: (12 + 2) = 14

เป็นต้น

19 เค้ก -> 16 -> 14 -> 12 -> 11 -> 10 -> 9 -> 8
18 เค้ก -> 15 -> 13 -> 11 -> 11 -> 10 -> 8 -> 8 (กฎ 3)

สำหรับ 18 เค้กหมุนรอบสุดท้ายจะไม่ได้เก็บเค้กใด ๆ ดังนั้นจำนวนเค้กขั้นต่ำสำหรับ 25% / 2 วันคือ 19

input: 25 2
output: 19

ตัวอย่างที่ 2:

ภาษีเค้ก 90%, 1 คืนเค้กหมุนรอบ

100 เค้ก -> 11 -> 2 -> 1 (กฎ 4)

หมุนรอบที่สามไม่ได้เก็บเค้กใด ๆ ดังนั้นจึงเป็นไปไม่ได้ที่จะเดินทางใน 90% / 1 วันแม้จะเริ่มต้นด้วยจำนวนเค้กสูงสุด

input: 90 1
output: 0

ข้อมูล

จัดทำกราฟอย่างรวดเร็วของค่าอินพุตและเอาต์พุต ฉันประหลาดใจที่นี่ไม่ได้ "ราบรื่น" (เหมือนเส้นโค้งของระฆังหรือคล้ายกัน); มีหมู่เกาะที่เห็นได้ชัดเจนหลายแห่ง

กราฟข้อมูล

ข้อมูลสำหรับผู้ที่สนใจ คอลัมน์ถูกแบ่งออกเป็นช่วง 5% แถวคือหน่วยของช่วงเวลาการคืนเงินเค้ก 1 ครั้ง (excel หมุนภาพ) คุณสามารถดูได้ว่ามีการคืนเงินไม่เกิน 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 ฉันจะทำรอบพรุ่งนี้

บานี่คือเหตุผลที่ c # ไม่สามารถมีสิ่งที่ดีได้

ดูเหมือนว่ากฎข้อ 2 จะไม่รวมการหมุนรอบที่ได้รับเพียงเศษเสี้ยวของเค้กซึ่งควรทำให้สมมติฐาน 4 ซ้ำซ้อน แต่คุณพูดในตัวอย่างที่ 2 ว่าการหมุนรอบตัวที่สามจะได้รับเพียง 0.8 เค้ก
Dennis

มีข้อขัดแย้งในสเป็ค ใน25 2กรณีเค้ก 11 ชิ้นคุณให้เค้กโทรลล์ 2.75 และได้รับ 2 กลับดังนั้นโทรลล์จะเก็บค่า. 75 (+ 25) และคุณเอาตัวรอด ใน90 1กรณีเค้ก 2 ใบคุณให้ค่าโทรลล์ 1.8 และได้รับ 1 คืนดังนั้นโทรลล์จะเก็บ. 8 (+. 2) แต่คุณตาย
TwiNight

คำตอบ:


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ให้ผลลัพธ์ที่ไม่ถูกต้องเช่นกัน
Dennis

1
@ เดนนิสคงที่ขอบคุณ!
Martin Ender

@Dennis นั่นบันทึกไบต์จริงๆ ฉันหวังว่า CJam จะปิดตัวลงจากนั้นฉันสามารถกำหนดบล็อกได้ตั้งแต่ต้นว่าจะทำการลดหย่อนภาษีและใช้สิ่งนั้นแทนการใช้ตัวแปรสองตัว บางทีฉันสามารถบันทึกบางอย่างโดยใช้ ARGV แทน STDIN ขอฉันดูหน่อย
Martin Ender

5

CJam, 44 40 38 37 35 ไบต์

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

หรือเมื่อใช้อาร์กิวเมนต์บรรทัดคำสั่งและ {}#เคล็ดลับ33 ไบต์ :

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

การไม่ให้สิ่งนี้เป็นหลักของฉันเป็น{}#แนวทางได้รับแรงบันดาลใจจากคำตอบของมาร์ติน

ตัวอย่างการเรียกใช้:

การป้อนข้อมูล:

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";

ลองออนไลน์ได้ที่นี่


และตอนนี้สิ่งที่เหลือคือการรอให้เดนนิสเข้ามาและเอาชนะเราทั้งคู่ ;)
Martin Ender

ไม่ได้อยู่ใน CJam;) (หวังว่า)
เครื่องมือเพิ่มประสิทธิภาพ

ฉันชอบ]W=เคล็ดลับจริงๆแต่จนถึงตอนนี้ฉันพยายามใช้มันทุกครั้งจนจบด้วยจำนวนตัวอักษรที่เหมือนกัน
Martin Ender

@ MartinBüttner - ใช่ฉันเหมือนกัน
เครื่องมือเพิ่มประสิทธิภาพ

1
@Dennis - ควรใช้งานได้ในขณะนี้พร้อมสิทธิประโยชน์เพิ่มเติมของโค้ดที่สั้นกว่า 2 ไบต์: D
เครื่องมือเพิ่มประสิทธิภาพ

4

APL (39)

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

คำอธิบาย:

  • T R←⎕: อ่านตัวเลขสองตัวจากแป้นพิมพ์และเก็บไว้ในT(ภาษี) และR(คืน)
  • Z←⍳M←100: จัดเก็บหมายเลข100ในMและตัวเลขทั้งหมดจาก1การใน100Z
  • {... }⍣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;
}

ถ้ามันใช้งานได้มันจะใช้ได้กับ startcakes ที่เป็นไปได้ทั้งหมดไม่ใช่จาก 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 เค้กในตอนแรก
Martin Ender


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(ภาษี) และy(คืน)
⍳x÷←100หารxด้วย 100 แล้วสร้างอาร์เรย์ 1 ถึง 100

{y+⍵-⌈⍵×x}⍣6เรียกฟังก์ชั่น "pass bridge" 6 ครั้ง:
⌈⍵×xจำนวนเค้กที่คุณมี,
⍵-คูณอัตราภาษี, ปัดเศษขึ้น (จำนวนเงินที่คุณจ่าย) ลบออกจากจำนวนเค้กที่คุณมี
y+เพิ่มการคืนเงิน

จากนั้นคุณจะได้อาร์เรย์ 100 องค์ประกอบที่แสดงจำนวนเค้กที่คุณเหลืออยู่หลังจากข้ามสะพาน 6 แห่งหากคุณเริ่มต้นด้วย 1 ~ 100 เค้ก หากต้องการดูว่าคุณสามารถข้ามสะพานสุดท้ายได้หรือไม่ให้ตรวจสอบว่าคุณอยู่เหนือขีด จำกัดy÷xหรือไม่ อีกวิธีหนึ่ง:
คูณอาร์เรย์ด้วยx
y<เครื่องหมายถ้ามากกว่าy

สุดท้าย
1⍳⍨หาดัชนีการเกิดขึ้นครั้งแรกของ1(จริง), ส่งคืน101หากไม่พบ
101|mod 101


1

C 128

ค่อนข้างคล้ายกับโซลูชัน C อื่น ๆ แต่ฉันคิดว่าคงหนีไม่พ้น เคล็ดลับหลักคือการแบ่งออกจากวงในที่มีค่าแตกต่างกันขึ้นอยู่กับว่ามันจะเสร็จสมบูรณ์หรือไม่ สิ่งนี้อนุญาตให้ฉันใช้หรือไม่: เมื่อฉันทำไม่ได้ถ้าฉันหยุดพัก;

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

Ungolfed

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.