ช่วยฉันฉันหลงทางในมหาสมุทร!


11

บทนำ

วันนี้ฉันไปตกปลาตามลำพังกับเรือแคนูโชคไม่ดีที่ฉันหลับไปและกระแสน้ำก็พาฉันออกไปฉันทำพายหายตอนนี้คืนและฉันก็หายไปในมหาสมุทร! ฉันไม่สามารถเห็นชายฝั่งดังนั้นฉันต้องอยู่ไกล!

ฉันมีโทรศัพท์มือถือของฉัน แต่ใช้งานไม่ได้เพราะมันเปียกด้วยน้ำทะเลเค็มฉันไม่สามารถพูดคุยหรือได้ยินอะไรเพราะไมค์และลำโพงโทรศัพท์เสีย แต่ฉันสามารถส่ง SMS ถึงเพื่อนที่อยู่บนชายหาดของชายฝั่ง!

เพื่อนของฉันมีไฟฉายที่ทรงพลังมากและเขายกมันขึ้นบนต้นไผ่เพื่อแสดงให้ฉันเห็นทิศทางที่ถูกต้อง แต่ฉันไม่สามารถเข้าแถวได้เพราะฉันไม่มีพายดังนั้นฉันต้องบอกเขาว่าฉันเป็นใคร จับฉัน!

เพื่อนของฉันบอกฉันว่าเขาเก็บคบเพลิงไว้ที่ 11.50 เมตรบนระดับน้ำทะเลและฉันเห็นแสงเหนือขอบฟ้า ตอนนี้ฉันจำได้แค่จากโรงเรียนว่ารัศมีของโลกควรอยู่ที่ 6371 กม. ที่ระดับน้ำทะเลและฉันนั่งในเรือแคนูของฉันเพื่อให้คุณคิดว่าตาของฉันอยู่ที่ระดับน้ำทะเลเช่นกัน

งาน

เพื่อนของฉันกำลังคบเพลิงเป็นครั้งคราว (ตอนนี้อยู่ที่ 12.30 เมตร) โปรดเขียนโปรแกรมหรือฟังก์ชั่นเต็มรูปแบบที่จะช่วยฉันคำนวณระยะทางจากตำแหน่งของเพื่อนฉัน!

นี่คือแผนภาพ (ไม่ปรับขนาด):

ป้อนคำอธิบายรูปภาพที่นี่

จุดสีส้มที่มีชื่อว่าMฉันจุดสีแดงที่มีป้ายกำกับTคือไฟฉาย เส้นสีเขียวคือระยะเชิงเส้นระหว่างMถึงT

อินพุต

ใช้ความสูงคบเพลิงเป็นhเมตรที่ระดับน้ำทะเลซึ่งฉันเห็นอยู่ด้านบนของขอบฟ้าในรูปแบบของจำนวนจุดลอยตัวที่มีความแม่นยำทศนิยมสองตำแหน่ง (ที่มีความแม่นยำ 1 เซนติเมตรหรือ 0.01 เมตร) ใน รวมตั้งแต่ 0 ถึง 100

เอาท์พุต

คุณควรคืนความยาวยูคลิดของเส้นสีเขียวด้วยความแม่นยำ 1 ซม. ตัวอย่างเช่นถ้าคุณส่งออกเป็นเมตรควรมีทศนิยมสองตำแหน่ง (อย่างน้อย) เอาต์พุตสามารถเป็นได้ทั้งเมตรหรือกิโลเมตร แต่เคารพความถูกต้อง

กรณีทดสอบ:

ค่าทั้งหมดเป็นเมตร

11.5 > 12105.08
13.8 > 13260.45

กฎระเบียบ

รหัสที่สั้นที่สุดชนะ


ผลลัพธ์จะต้องถูกต้องทางคณิตศาสตร์หรือไม่เป็นไรถ้า 2 ทศนิยมแรกตกลง ฉันหมายถึง hxh นั้นมีขนาดเล็กเมื่อเทียบกับ 2xRxh และสามารถละเลยในระยะทางเล็ก ๆ ได้ (R คือรัศมีของโลกและ h คือความสูงของคบเพลิง)
Osable

@Oableable 2 Decimals แรกก็โอเคถ้าคุณส่งออกในหน่วยเมตร
Mario

ช่วงของอินพุตคืออะไร
Osable

@Osable คุณสามารถพิจารณาอินพุตได้ตั้งแต่ 0 ถึง 100 (มากเกินจำเป็น / เป็นไปได้ในกรณีนี้)
มาริโอ

1
คุณควรลองแลกเปลี่ยน Coast Guard Stack - code golferse ไม่สามารถช่วยให้คุณออกไปจากมหาสมุทรได้!
corsiKa

คำตอบ:


4

05AB1E ,13 12 10 ไบต์

บันทึก 2 ไบต์ด้วย Emigna

เนื่องจากไม่มีฟังก์ชันตรีโกณมิติที่จะเรียกใช้โดยใช้สมมติฐานของ OP ว่าโลกอยู่ในระนาบเดียวจึงเป็นไปได้ที่จะสร้างโซลูชัน 05AB1E

•1#oC•+¹*t

           For understanding purposes input is referred to as 'h'
•1#oC•     Push 12742000 [ = 2*R, where R is the radius of earth]
      +    Compute 2*R+h
       ¹*  Multiply by h. Result is (2*R*+h)*h
         t Take the square root of it and implicitly display it

ลองออนไลน์!


1
12742000สามารถเขียนเป็น•1#oC•
Emigna

สำหรับการอ้างอิงจะมีขนาด 9 ไบต์: •1#oC•+*tใน2sable
Emigna

สตริงมีที่มากับตัวเลข ... ฐาน 214 หรือไม่ 05AB1E ประสบปัญหาการขาดเอกสารเกี่ยวกับฟังก์ชั่นพิเศษบางครั้ง คำตอบที่ดี 2sable ยัง ฉันพบข้อมูลเกี่ยวกับเรื่องนี้เมื่อไม่กี่วันที่ผ่านมา แต่ฉันไม่ได้คิดถึงการใช้งานสำหรับคำถามนี้
Osable

แก้ไข. มันคือเลขฐาน 10 ตัวที่เข้ารหัสในฐาน 214
Emigna

ผลสามารถทำได้ด้วยตรีโกณมิติ แต่อาจนานกว่านั้น
มาริโอ

4

Python 34 34ไบต์:

( -8 ไบต์ขอบคุณ Osable! )

lambda i:(i*(i+12742))**.5

ฟังก์ชั่นแลมบ์ดานิรนาม ใช้อินพุตเป็นกิโลเมตรและเอาต์พุตเป็นกิโลเมตร print(<Function Name>(<Input>))เรียกว่าเป็น


lambda i:(i*(i+12742))**.5จะสั้นกว่านี้
Osable

@ ใช้ได้ดี! ฉันเพิ่งจะทำเช่นนั้น :)
R. Kap

หากมีความอดทนทางคณิตศาสตร์ให้ความแตกต่างระหว่างiและ 12742 การแสดงออกสามารถสั้นลงดังนั้น:(i*12742)**.5
Osable

ผลลัพธ์ไม่ถูกต้อง 11.5m -> ~ 380km แทน ~ 12km
GB

@GB โปรแกรมอ่านอินพุตเป็นกิโลเมตร
Osable

4

PHP, 34 ไบต์

<?=sqrt((12742e3+$h=$argv[1])*$h);

แตกหัก

   r^2+x^2=(r+h)^2      # Pythagoras base
   r^2+x^2=r^2+2rh+h^2  # right term distributed
       x^2=    2rh+h^2  # -r^2
       x =sqrt(2rh+h^2) # sqrt

จนถึงตอนนี้มันเหมือนกับคำตอบ Mathematica เก่า ๆ

sqrt(2*6371e3*$h+$h*$h) # to PHP
sqrt(14742e3*$h+$h+$h)  # constants combined
sqrt((14742e3+$h)*$h)   # conjugation to save a byte
((14742e3+$h)*$h)**.5   # same size

ตอนนี้สิ่งที่ต้องทำคือการเพิ่มอินพุท=$argv[1]และเอาท์พุท<?=- ทำ


4

dc, 16 11 ไบต์:

?d12742+*vp

พร้อมต์สำหรับอินพุตผ่านบรรทัดรับคำสั่งเป็นกิโลเมตรแล้วส่งเอาต์พุตระยะทางเป็นกิโลเมตร

คำอธิบาย

?           # Prompt for input
 d          # Duplicate the top-of-stack value
  12742     # Push 12,742 onto the stack
       +    # Pop the top 2 values of the stack and push their sum
        *   # Pop top 2 values of the stack and push their product
         v  # Pop the remaining value and push the square root
          p # Output the result to STDOUT

สิ่งนี้ใช้ประโยชน์จากสิ่งต่อไปนี้:

((6371+h)**2-6371**2)**.5 
=> ((6371**2+12742h+h**2)-6371**2)**0.5 
=> (h**2+12742h)**0.5 
=> (h*(h+12742))**0.5


4

Haskell, 22 ไบต์

d h=sqrt$h*(h+12742e3)

การใช้งาน:

Prelude> d 11.5
12105.087040166212

Pointfree: (23 ไบต์)

sqrt.((*)=<<(+12742e3))


2

Mathematica ขนาด 16 ไบต์

งานเหล่านี้สำหรับทั้งอินพุตและเอาต์พุตในหน่วยกิโลเมตร:

(12742#+#*#)^.5&
((12742+#)#)^.5&

นี่เป็นแอปพลิเคชันอย่างง่ายของ Pythagoras สำหรับปัญหา:

   x*x + R*R = (R+h)*(R+h)
=> x*x = (R+h)*(R+h) - R*R
       = R*R + 2*R*h + h*h - R*R
       = 2*R*h + h*h
=>   x = √(2*R*h + h*h)

2

Jelly, 9 ไบต์ในหน้ารหัสของ Jelly

ฉันตัดสินใจที่จะเขียนโปรแกรมเป็นภาษากอล์ฟ ฉันพบอัลกอริทึมที่มีประสิทธิภาพมากกว่าที่คนอื่นกำลังใช้อยู่ (อย่างน้อยในระยะทางสั้น ๆ อย่างที่ถาม) แต่ต้องใช้ตัวเลขทศนิยมที่แท้จริงซึ่ง Jelly ดูเหมือนจะไม่สามารถบีบอัดได้ดังนั้น Pythagoras มันคือ.

+“Ȯịż’×µ½

คำอธิบาย:

 “Ȯịż’     12742000, compressed base-250
+          add to argument
      ×    multiply with original argument
       µ   separator to avoid what would otherwise be a parsing ambiguity
        ½  square root everything seen so far
           implicit output at EOF

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

Jelly, 7 ไบต์ในหน้ารหัสของ Jelly

דȮịż’½

ตามที่ฉันได้อธิบายไว้ในคำตอบอื่น ๆการประมาณอนุกรมของการประมาณพีทาโกรัสนั้นให้ผลลัพธ์ที่ดีกว่าความยาวที่รวมอยู่ในคำถาม ในขณะที่ฉันกำลังเขียนฉันรู้ว่าแทนที่จะคำนวณสแควร์รูทของ 12742000 ล่วงหน้าฉันสามารถคูณจำนวนด้วย 12742000 ก่อนแล้วจึงสแควร์รูททั้งสองในเวลาเดียวกัน โดยทั่วไปจะเทียบเท่ากับสูตรอื่นโดยไม่มีการเพิ่มและสามารถสร้างได้จากโปรแกรมก่อนหน้าผ่านการลบการเพิ่มออก นี่ช่วยประหยัดสองไบต์เนื่องจากแยกวิเคราะห์ได้อย่างชัดเจนตอนนี้และเราไม่ต้องการµอะไรอีกแล้ว


ฉันตัดสินใจที่จะไม่ใช้การเพิ่มประสิทธิภาพนี้เพราะมันไม่ได้ให้ค่าเท่ากันถ้าคุณดูหน่วยเซนติเมตร มันจะประหยัด 2 ไบต์ใน 05AB1E
Osable

ด้วยการปรับให้เหมาะสมฉันจะได้ผลลัพธ์ที่ 12105.081577585506 และ 13260.452480967608 สิ่งเหล่านี้อยู่ใกล้กับผลลัพธ์ของกรณีทดสอบมาก ถ้าไม่มีฉันจะได้ 12105.087040166212 และ 13260.459661716106 ซึ่งอยู่ไกลออกไป (และอันหลังนั้นไม่ถูกต้องในหน่วยเซนติเมตรปัดเศษเป็น 13260.46) ดังที่กล่าวไว้ในคำตอบอื่น ๆ การปรับให้เหมาะสมเกิดขึ้นใกล้เคียงกับค่าที่ถูกต้องมากกว่ารหัสที่ได้รับการปรับให้เหมาะสมเพราะมันมีข้อผิดพลาดสองอย่างที่ส่วนใหญ่ยกเลิกซึ่งกันและกันมากกว่าหนึ่งที่ไม่มีอะไรจะยกเลิก

เนื่องจากคุณเพิ่งโหวตให้ "ปล่อยให้เปิด" ในคิวการตรวจทานฉันคิดว่าคุณเชื่อว่าคุณรู้คำตอบของคำถามที่ฉันขอชี้แจงในความคิดเห็น โปรดแก้ไขคำถามเพื่อไม่ให้คลุมเครือ
Peter Taylor

1
คำถามนั้นไม่คลุมเครือ: ผู้เขียนต้องการทราบระยะทางถึงเพื่อนของเขาเพื่อช่วยนำทาง เขาสามารถกำหนดตำแหน่งของคบเพลิงได้อย่างแม่นยำ 0.1 เมตร (เราสามารถระบุได้จากเรื่องที่เล่า) นี่จะทำให้เกิดความไม่แน่นอนประมาณ 1 เมตรจากเอาท์พุท ณ ระยะทางปัจจุบัน (หมายเหตุ: ผู้เขียนกำลังลอยไปมาดังนั้นจึงไม่น่าที่จะเคลื่อนที่ไปอย่างรวดเร็วมาก ... ) ดังนั้นสิ่งใดก็ตามที่ประมาณว่ามีความแม่นยำน่าจะเป็น ยอมรับได้ ส่วนหนึ่งของปัญหาคือการพิจารณาว่าคุณจะต้องแม่นยำในสถานการณ์นี้!

1
เอาต์พุตที่ร้องขอแสดง 2 ทศนิยมในหน่วยเมตร ดังนั้นความแม่นยำคาดว่าจะเป็น 1 เซนติเมตร ในความคิดเห็นของคำถาม OP กล่าวว่า h สามารถสูงได้ถึง 100 ด้วย h = 100 มีความคลาดเคลื่อน 14 เซนติเมตรจากอัลกอริทึมดั้งเดิม
Osable

2

ทับทิม, 23

23 ไบต์ในกม

->h{(h*h+h*12742)**0.5}

25 ไบต์ในหน่วยเมตร

->h{(h*h+h*12742e3)**0.5}

1

Tcl, 49 ไบต์:

set A [get stdin];puts [expr ($A*($A+12742))**.5]

ฉันเป็นคนใหม่ต่อ Tcl ดังนั้นเคล็ดลับใด ๆ สำหรับการลงเล่นกอล์ฟนี้จึงเป็นที่นิยมอย่างมาก เช่นเดียวกับคำตอบอื่น ๆ ของฉันพร้อมรับคำสั่งอินพุตบรรทัดคำสั่งเป็นกิโลเมตรและเอาต์พุตเป็นกิโลเมตร เป็นหลักการปรับ Tcl ของฉันที่มีอยู่dcและpythonคำตอบ


มีsหายไปเมื่อได้รับs
sergiol

1

x86_64 + รหัสเครื่อง SSE ขนาด 16 ไบต์

ไบต์ของโปรแกรมอยู่ทางซ้าย (เป็นเลขฐานสิบหก) มีการถอดแยกชิ้นส่วนทางด้านขวาเพื่อให้อ่านง่ายขึ้นเล็กน้อย นี่คือฟังก์ชั่นที่เป็นไปตามแบบแผน x86_64 ปกติสำหรับฟังก์ชั่นการรับและส่งกลับจำนวนจุดลอยตัวที่มีความแม่นยำเดียว (ใช้อาร์กิวเมนต์ใน% xmm0 และส่งกลับคำตอบในรีจิสเตอร์เดียวกันและใช้% xmm1 และ% eax เป็นแบบแผนการโทรเดียวกันที่โปรแกรม C จะใช้และคุณสามารถเรียกใช้ฟังก์ชันได้โดยตรงจากโปรแกรม C ซึ่งเป็นวิธีที่ฉันทดสอบ)

b8 80 19 5f 45          mov    $0x455f1980,%eax
66 0f 6e c8             movd   %eax,%xmm1
0f 51 c0                sqrtps %xmm0,%xmm0
0f 59 c1                mulps  %xmm1,%xmm0
c3                      retq

แม้ว่าจะมีการถอดแยกชิ้นส่วน แต่ก็ยังต้องการคำอธิบาย อย่างแรกมันก็คุ้มค่าที่จะพูดคุยเกี่ยวกับสูตร คนส่วนใหญ่ไม่สนใจความโค้งของโลกและใช้สูตรของพีธากอรัสในการวัดระยะทาง ฉันก็ทำเช่นกัน แต่ฉันใช้การประมาณการขยายตัวอนุกรม ฉันแค่ใช้เทอมที่เกี่ยวข้องกับพลังแรกของอินพุตและไม่สนใจพลังที่สามห้าเจ็ดและอื่น ๆ ซึ่งทั้งหมดล้วนมีอิทธิพลเพียงเล็กน้อยในระยะสั้นนี้ (นอกจากนี้การประมาณแบบพีทาโกรัสให้ค่าต่ำในขณะที่คำต่อท้ายในการขยายอนุกรมให้บริการเพื่อลดค่าเช่นโดยการเพิกเฉยต่อปัจจัยเล็กน้อยที่จะผลักดันการประมาณการไปในทิศทางที่ผิด ผลลัพธ์ที่แม่นยำยิ่งขึ้นโดยใช้สูตรที่มีความแม่นยำน้อยกว่า) สูตรจะกลายเป็น√12742000×√h;0x455f1980.

สิ่งต่อไปที่อาจทำให้คนสับสนคือสาเหตุที่ฉันใช้คำสั่งแบบเวกเตอร์สำหรับสแควร์รูทและทวีคูณ %xmm0และ%xmm1สามารถเก็บตัวเลขจุดลอยตัวที่มีความแม่นยำเดียวได้สี่ตัวแต่ละอัน เหตุผลที่นี่ง่ายจริงๆ: การเข้ารหัสของพวกเขาสั้นกว่าหนึ่งไบต์ของคำแนะนำเซนต์คิตส์และเนวิสที่สอดคล้องกัน ดังนั้นฉันสามารถทำให้ FPU ทำกลุ่มงานพิเศษที่มีรูทสแควร์รูทและศูนย์การคูณเพื่อช่วยตัวเองสองไบต์ในวิธีที่โดดเด่นมากของอัลกอริทึมภาษากอล์ฟทั่วไป (ฉันเรียก x86 แอสเซมเบลอร์ภาษากอล์ฟของแอสเซมเบลอร์ในขณะที่แชทกลับมาและฉันยังไม่เปลี่ยนใจในเรื่องนั้น

จากนั้นอัลกอริทึมง่ายมาก: โหลด%xmm1ด้วย√12742000ผ่าน%eax(ซึ่งสั้นกว่าในแง่ของไบต์มากกว่าการโหลดจากหน่วยความจำจะเป็น), สแควร์รูทอาร์กิวเมนต์ (และสามศูนย์), องค์ประกอบที่สอดคล้องกันคูณของ%xmm1และ%xmm0(เราเพียงดูแล เกี่ยวกับองค์ประกอบแรก) จากนั้นส่งคืน


1

Minkolang v0.15, 22 ไบต์

ndd*$r'12742000'*+1MN.

ลองออนไลน์!

n                               gets input in the form of a number
 dd                             duplicates it twice
   *                            multiplies 2 of the duplicates with each other
                                STACK: [h, h*h]
    $r                          swap top two stack values
                                STACK: [h*h, h]
      '12742000'*               push this number and multiply the original input by it
                                STACK: [h*h, h*12742000]
                 +1M            adds the two values and takes their square root
                                STACK: [sqrt(h*h+h*12742000)]
                    N.          output as a number and end program

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.