นอร์ทโดยนอร์ทโดยนอร์ทโดยตะวันออกเฉียงใต้


30

รับสตริงของ N, S, E และ W, ส่งลูกปืน (มุมตามเข็มนาฬิกาจากทิศเหนือเป็นองศา), แก้ไขให้ถูกต้องถึงทศนิยม 5 ตำแหน่ง

ในรูปแบบเข็มทิศแบบดั้งเดิมสตริงจะประกอบด้วยอักขระเพียง 2 ตัวเท่านั้น (เช่น NNW หรือ ESE) ที่นี่คุณยังจะต้องยอมรับสตริงที่มีทั้งหมด 4 (เช่น WNNNSE) การใช้สัญลักษณ์เพียง 2 ตัวช่วยให้มนุษย์เข้าใจความหมายได้โดยสัญชาตญาณ การอนุญาตให้ใช้ 4 สัญลักษณ์ทำให้การอ่านเป็นเรื่องที่น่ากลัว แต่ช่วยให้สามารถอธิบายการแบกได้อย่างแม่นยำ

(ตามที่ระบุไว้ในความคิดเห็นโดยผู้ใช้235,712มันปรากฎว่าคุณสามารถพิสูจน์ได้ว่าสำหรับแบริ่งใด ๆ ที่ได้รับสตริงสัญลักษณ์ 4 จะมีความยาวเท่ากับสตริงสัญลักษณ์ 2 ดังนั้นฉันได้ท้าทายนี้บนสมมติฐานที่ผิดพลาด หวังว่าการขาดวัตถุประสงค์เชิงปฏิบัตินี้จะไม่เบี่ยงเบนความสนใจของคุณไปกับความท้าทาย ... )

วิธีการที่แน่นอนมีการอธิบายด้านล่างและเทียบเท่ากับสัญกรณ์ดั้งเดิม (มันขยายตัวมากกว่าที่จะเปลี่ยนมัน)

อินพุต

  • NESWการป้อนข้อมูลที่เป็นสายเดียวที่มีเพียงตัวละคร
  • อินพุตอาจเป็นลำดับอักขระหากคุณต้องการโดยไม่รวมการประมวลผลล่วงหน้า ตัวอย่างเช่น[N, [E, [S, [W]]]]ไม่อนุญาตให้ใช้รายการซ้อนเพื่อช่วยในการประมวลผลคำสั่ง
  • ไม่อนุญาตให้ใช้อักขระอื่น คุณอาจจะไม่ใช้สตริงของแทน1234NESW

เอาท์พุต

  • ผลลัพธ์จะต้องเป็นตัวเลขทศนิยมหรือการแสดงสตริงของหนึ่ง (ไม่ใช่เหตุผล / เศษส่วน)
  • ไม่จำเป็นต้องแสดงค่าศูนย์ต่อท้าย ถ้าแบริ่งเป็น9.00000แล้วเอาท์พุท9ยังนับว่าถูกต้องถึงทศนิยม 5 ตำแหน่ง
  • เอาต์พุตอยู่ในช่วง [0, 360) นั่นคือรวมถึง 0 แต่ไม่รวม 360
  • ความถูกต้องถูกตรวจสอบโดยการปัดเศษผลลัพธ์เป็นทศนิยม 5 ตำแหน่ง ถ้าลูกปืนคือ 0.000005 รอบนี้จะเป็น 0.00001 เอาต์พุต 0.00001 และ 0.000005 ทั้งคู่ถูกต้อง
  • เอาท์พุทในสัญกรณ์ทางวิทยาศาสตร์สำหรับบางอินพุตเป็นที่ยอมรับ ยกตัวอย่างเช่นแทน1e-50.00001

การแปลง

  • เข็มทิศจุดNเดียวE, Sและ, Wสอดคล้องกับ 0, 90, 180 และ 270 องศาตามลำดับ
  • การเตรียมสิ่งเหล่านี้ให้กับสตริงจะส่งผลให้ตลับลูกปืนที่แบ่งตลับลูกปืนของอักขระเดี่ยวและตลับลูกปืนของสายอักขระเดิม
  • แบริ่งแบ่งครึ่งที่ใกล้เคียงที่สุดที่เป็นไปได้ถูกเลือกไว้ดังนั้น NE จึงเป็น 45 องศาไม่ใช่ 225 องศา
  • สิ่งนี้ไม่ชัดเจนยกเว้นมุมที่จะแบ่งออกเป็น 180 องศา ดังนั้นNS, SNและWE, EWสอดคล้องกับแบริ่งที่ไม่ได้กำหนดและอินพุตจะไม่สิ้นสุดในสิ่งเหล่านี้ อย่างไรก็ตามอาจปรากฏที่ใดก็ได้ในสตริงอินพุตเนื่องจากจะไม่มีความกำกวม
  • หากอักขระสองตัวสุดท้ายเหมือนกันตัวละครสุดท้ายจะซ้ำซ้อนเนื่องจากการแบ่งจะกลับมาเป็นเหมือนเดิม ตั้งแต่นี้จะเพิ่มอะไรในสัญกรณ์รหัสของคุณไม่จำเป็นต้องจัดการนี้ ดังนั้นNN, EEและSS, WWสอดคล้องกับแบริ่งที่ไม่ได้กำหนดและอินพุตจะไม่สิ้นสุดในสิ่งเหล่านี้ อย่างไรก็ตามอาจปรากฏที่ใดก็ได้ในสตริงป้อนข้อมูล

ตัวอย่าง

N: 0
E: 90
S: 180
SE: halfway between S and E: 135
NSE: halfway between N and SE: 67.5
NNSE: halfway between N and NSE: 33.75
NNNSE: halfway between N and NNSE: 16.875
NNNNSE: halfway between N and NNNSE: 8.4375

กรณีทดสอบ

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

ผลลัพธ์ของเคสทดสอบจะแสดงเป็นทศนิยม 5 ตำแหน่งและเพื่อความแม่นยำโดยพลการ ทั้งสองเป็นผลลัพธ์ที่ถูกต้อง

WNE 337.5 337.5
WEN 337.5 337.5
WEWEWEWEWEWEWEWEWEWEWEN 330.00001 330.000007152557373046875
NESWNESWNESWNESWNESWNESWNESW 90 89.99999932944774627685546875
NNNNNNNNNNNNNNNNNNNNNNNE 0.00001 0.0000107288360595703125
NNNNNNNNNNNNNNNNNNNNNNNW 359.99999 359.9999892711639404296875
SNNNNNNNNNNNNNNNNNNNNNNNE 90.00001 90.00000536441802978515625
SNNNNNNNNNNNNNNNNNNNNNNNW 269.99999 269.99999463558197021484375

เกณฑ์การให้คะแนน

นี่คือรหัสกอล์ฟคะแนนคือความยาวของซอร์สโค้ดในหน่วยไบต์และการชนะที่สั้นที่สุด


การคุยโวโอ้อวด

ฉันทำผิดที่คิดว่า "North by North West" เป็นทิศทางเข็มทิศที่ถูกต้อง ความผิดพลาดที่มีความสุขเพราะมันนำไปสู่ความคิดที่ท้าทาย แต่จากนั้นฉันค้นพบจากหน้า Wikipedia :

"ชื่อเรื่องของภาพยนตร์ Alfred Hitchcock 1959 ทางตะวันตกเฉียงเหนือของ Northwest ไม่ใช่จุดกำกับทิศทางของเข็มทิศ 32 ลม แต่ ภาพยนตร์มีการอ้างอิงถึง Northwest Airlines "

นอกจากนี้ยังปรากฎว่าวิธีการที่ใช้สำหรับความท้าทายนี้สอดคล้องกับจุดเข็มทิศดั้งเดิมจนถึงและรวมถึงเข็มทิศ 16 จุดเท่านั้น เข็มทิศ 32 ลมที่อธิบายไว้ในหน้านั้นมีความแตกต่างกันเล็กน้อยและฉันมองข้ามการมีอยู่ของมันสำหรับความท้าทายนี้

ในที่สุดสำหรับทุกคนที่คิดว่าฉันควรใช้ "ตะวันออกเฉียงใต้" แทน "ตะวันออกเฉียงใต้".


WNNNSE<= ผลลัพธ์ของรายการตัวอย่างนี้จะเริ่มต้นที่โพสต์ของคุณเมื่อใด มันฟังดูไม่ถูกต้องสำหรับฉัน แต่มันยากที่จะบอก
Tensibai

@Tensibai สำหรับการป้อนข้อมูลการส่งออกจะเป็นWNNNSE 323.4375ดูหัวข้อตัวอย่างสำหรับคำแนะนำที่จะนำไปใช้ในทางเดียวกันกับกรณีนี้
trichoplax

อินพุตเหมือนf(N,N,N,S,E)โอเคไหม
Karl Napf

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

2
"การอนุญาตให้ใช้ 4 สัญลักษณ์ทำให้การอ่านเป็นเรื่องที่น่ากลัว แต่ช่วยให้สามารถอธิบายการแบกได้อย่างแม่นยำยิ่งขึ้น" - คุณแน่ใจเกี่ยวกับที่? ดูเหมือนว่าอินพุตทั้งหมดที่อธิบายถึงตลับลูกปืนชนิดเดียวกันนั้นมีความยาวเท่ากันเนื่องจากถ้าคุณกำหนดให้แต่ละตลับมีเหตุผล dyadic จาก 0 ถึง 1 สตริงที่มีความยาว N กับ N> 1 จะสอดคล้องกับเหตุผล dyadic กับตัวหาร 2 ^ (N) +1) ด้วยเงื่อนไขต่ำสุด นอกจากนี้การอนุญาตให้มีตัวอักษรที่แตกต่างกันมากกว่า 2 ตัวในตลับลูกปืนเพิ่มพลังที่ไม่แสดงออก ตลับลูกปืนที่แสดงด้วยตัวอักษร 3 หรือ 4 ตัวสามารถแสดงด้วย 2
user2357112 รองรับ Monica

คำตอบ:


13

JavaScript (ES6), 84 80 78 74 72 ไบต์

บันทึกเป็นไบต์ด้วย @Titus, 1 ขอบคุณ @Neil

f=([c,...s],b="NESW".search(c))=>b*90-(s[0]?(b-=f(s)/90)-4*(b*b>4):0)*45

มันใช้เวลาสักครู่ แต่ฉันคิดว่าในที่สุดฉันก็ทำให้สูตรสมบูรณ์ ...

ตัวอย่างการทดสอบ

คำอธิบาย

เริ่มจากกรณีที่ง่ายที่สุด: สตริงอักขระเดี่ยว ผลลัพธ์จะเป็นเพียงตำแหน่ง (0 ดัชนี) ในสตริงNESWคูณด้วย 90

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

สำหรับสตริงที่ยาวกว่านั้นผลลัพธ์จะอยู่กึ่งกลางระหว่างผลลัพธ์ของอักขระตัวแรกและผลลัพธ์ของส่วนที่เหลือของสตริง นี่สามารถสรุปได้ด้วยวิธีต่อไปนี้:

  • หากอินพุตเป็นอักขระเดี่ยวให้ส่งคืนดัชนีในสตริงคูณNESW90
  • มิฉะนั้นส่งคืนดัชนีของถ่านตัวแรกในสตริงคูณNESW45 บวกด้วยครึ่งหนึ่งของผลลัพธ์ของสตริงที่เหลือ เพิ่ม 180 พิเศษถ้าความแตกต่างที่แน่นอนระหว่างสองมากกว่า 90

วิธีที่ยอดเยี่ยมในการตัดอักขระตัวแรกออกจากสตริง! คุณสามารถบันทึกหนึ่งไบต์ถ้าคุณคำนวณกับค่าหารด้วย 45
ติตัส

@Titus ฉันสามารถบันทึก 2 ไบต์ด้วยเทคนิคนั้นขอบคุณ!
ETHproductions

1
searchแทนที่จะindexOfบันทึกเป็นไบต์
Neil

@ Neil ขอบคุณอีกครั้ง! ฉันพยายามตีกอล์ฟอีกสามครั้งโดยจัดเรียงสมการใหม่ทั้งหมด
ETHproductions

10

C # 6, 226 217 207 185 bytes

using System.Linq;double N(string s){double b=f(s.Last());foreach(var c in s.Reverse()){b=(b+f(c)+(b-f(c)>2?4:f(c)-b>2?-4:0))/2;b=(b+4)%4;}return b*90;}int f(char x)=>"NESW".IndexOf(x);

แก้ไข: -10 ไบต์โดยแนวคิด "การยืม" จากการส่งของ ETHproductions
-22 ไบต์ขอบคุณ @Titus

Ungolfed

// Call this method
double N(string s){
    // Initialize bearing with last direction
    double b=f(s.Last());
    // Do backward. Doing last direction once more doesn't impact result
    foreach(var c in s.Reverse()){
        // Average current bearing with new bearing, adjusted with wrapping
        b=(b+f(c)+(b-f(c)>2?4:f(c)-b>2?-4:0))/2;
        // Make bearing back to range [0,4)
        b=(b+4)%4;
    }
    // Change from "full circle = 4" unit to degree
    return b*90;
}
// helper method to convert direction to bearing. This returns bearing with full circle = 4.
int f(char x)=>"NESW".IndexOf(x);

ฉันคิดว่าคุณสามารถปรับช่วงของคุณกลับเป็น [0,360) ให้สั้นลงโดยใช้%
trichoplax

@trichoplax จะไม่ตัดทศนิยม?
ติตัส

1
@Titus C #% งานลอยเช่นเดียวกับจำนวนเต็ม
trichoplax

1
บันทึก 10 ไบต์กับแทนb=(b+360)%360; b+=b>360?-360:b<0?360:0;ประหยัดอีก 12 ไบต์กับหารทุกอย่างด้วย 90 return b*90;และ
ติตัส

1
นี่คืออีก 10 ไบต์: รวมสองการมอบหมายและลบวงเล็บ: b=(b+f(c)+(b-f(c)>2?4:f(c)-b>2?-4:0)+8)/2%4;จากนั้นแจกจ่าย+8ไปยังผลลัพธ์ที่ประกอบไปด้วยb=(b+f(c)+(b-f(c)>2?12:f(c)-b>2?4:8))/2%4;
ติตัส

8

PHP, 95 88 86 100 127 104 101 ไบต์

  • -7 ไบต์พร้อมตัวดำเนินการรวมศูนย์ว่าง
  • -2 ไบต์โดยไม่แทนที่N(และมากกว่านั้นเพราะช่วยให้สามารถนำการแปลไปยังส่วนหัวของลูป: Nเป็นความจริง แต่จะประเมิน0ในการคำนวณ)
  • +41 ไบต์สำหรับแก้ไขการแบ่งส่วน ( ไอ )
  • -7 ไบต์โดยตรงและ -16 เป็นแรงบันดาลใจทางอ้อมโดยรหัส @ ETHproductions´
  • -3 ไบต์โดยแทนที่strtrด้วยหนึ่งใน jugglings บิตของฉัน

for($i=strlen($s=$argv[1]);$i--;$p=($q+$p=$p??$q)/2+2*(abs($q-$p)>2))$q=ord($s[$i])/.8+3&3;echo$p*90;

นี่เป็นครั้งแรกอย่างเป็นทางการที่ฉันใช้ตัวดำเนินการรวมศูนย์ว่าง -rทำงานด้วย

PHP 7.1

ชดเชยสตริงลบใน PHP รุ่นที่จะเกิดขึ้นจะประหยัด 12 ไบต์:
แทนที่strlen($s=$argv[1])ด้วย0และมี$s$argv[1]


ไบต์ฟรีสำหรับ (เกือบ) ทุกคน:

  • การคำนวณด้วย 0,1,2,3 แทนที่จะเป็น 0,90,180,270 และการคูณผลลัพธ์สุดท้ายด้วย 90 จะประหยัดสองไบต์และอาจอนุญาตให้เล่นกอล์ฟต่อไป
  • มีรูปแบบบางอย่างในรหัส ASCII ของตัวละคร ลองหนึ่งในสิ่งเหล่านี้ในภาษาของคุณ:
    • (a/2%6+2)%5
    • a<87?a/2&3^3:3 หรือ a/2&3^3*(a<87)
    • a&1?a&2|a/4&1:0
    • a/.8-1&3

5

Python 3, 133 113 ไบต์

เพิ่งปรับปรุงคำตอบของ @ L3viathan เพราะฉันเพิ่งสร้างบัญชีนี้จึงไม่สามารถแสดงความคิดเห็นได้

d={"N":0,"E":.5,"S":1,"W":1.5}
def B(s):
 b=d[s[-1]]
 for c in s[::-1]:b=(b+d[c])/2+(abs(b-d[c])>1)
 return b*180

ยินดีต้อนรับสู่การเขียนโปรแกรมปริศนาและโค้ดกอล์ฟและการปรับปรุงที่ดี ...
trichoplax

ฉันไม่เห็นคำตอบของคุณ แต่ติตัสมีความคิดคล้าย ๆ กันรวมทั้งผมได้อีกผมลงไป 98 ตอนนี้ :)
L3viathan

5

05AB1E ,48 42 37 32 ไบต์

บันทึกแล้ว 6 ไบต์ขอบคุณ Emigna บันทึก 5 ไบต์ด้วยแนวคิดของ Titus ในการทำงานในช่วง [0,4 [และทวีคูณ 90 ด้วยท้าย " บันทึก 5 ไบต์ด้วยความชำนาญของ Adnan ในเรื่องการเปลี่ยนแปลงระหว่าง xor / modulo

ดังนั้นทุกมุมจะลดลงจากช่วง [0,360 [ถึงช่วง [0,4 [ตลอดการประมวลผล] ผลลัพธ์จะถูกคูณด้วย 90 และแสดง

Ç30^5%R¬U¦vXy+;DX-Ä0›2*+4%U}X90*

It can be divided into two sequentially called subprograms.
First program: convert input string into an array of the corresponding angles in range [0,4[
Ç      Take the ascii value of all input characters
 30^5% Dark ascii manipulation that yields [0,1,2,3] for [N,E,S,W]

Now we have an array of integers in range [0,4[.

Second program: actually compute the final angle
R                          Reverse the array
 ¬                         Take the first value (the last of the non-reversed array)
  U                        Pop it from the stack and set X to the same value
   ¦                       Strip the first element
    v                      For each remaining element
     Xy+;                  Compute the average value between the leftmost value and X
         DX-Ä0›            Push 1 if angular distance cast to integer is > 0 (i.e. if it is >= 1), 0 otherwise. It's equivalent to checking >= 90 degrees
               2*+         Multiply by 2 (=2 if angular distance is >= 1 and 0 otherwise) and add it to the formerly computed average value. It's equivalent to multiplying by 180
                  4%       Perform mod 4. It's equivalent to performing mod 360
                    U      Store the result back to X
                     }     End for, mandatory if input has only one character
                      X90* Push X*90 and implicitly display it

ลองออนไลน์!

แกนของการเล่นกอล์ฟ:

  • ไม่แน่ใจว่าจำเป็นต้องมี mod 4 หรือไม่ (จะช่วยประหยัด 2 ไบต์) กรณีทดสอบทั้งหมดไม่สามารถใช้งานได้ แต่อาจมีกรณีที่ยุ่งยาก หลักฐานทางคณิตศาสตร์เพื่อตรวจสอบหรือลบล้างมันจะเป็นรอยบน
  • ไม่มีสิ่งใดนอกจากการแสดงผลโดยนัย (เครื่องหมายอัญประกาศปิด, วงเล็บปิด)

1
ดูเหมือนจะไม่ได้ให้ผลลัพธ์ตามที่ร้องขอในกรณีทดสอบNNNNNNNNNNNNNNNNNNNNNNNEและ SNNNNNNNNNNNNNNNNNNNNNNNE
Emigna

2
แปลก. ตอนนี้ฉันก็ทำเช่นกัน ฉันจะต้องวางผิดหรืออะไรบางอย่างขอโทษ คุณสามารถย่อรหัสให้สั้นลงv"NESW"yk90*})R¬U¦vXy+;DX-Ä89›180*+360%U}Xได้
Emigna

1
คำอธิบายที่ดี! อาจมีค่ารวมถึงบันทึกย่อที่89›จริงหมายถึงส่วนจำนวนเต็มมากกว่า 89 ซึ่งเทียบเท่ากับการบอกว่าจำนวนสมบูรณ์มากกว่าหรือเท่ากับ 90 (ซึ่งยังคงทำงานได้ดีเพราะ 90 ไม่ควรเกิดขึ้น) ขณะนี้ความคิดเห็นในรหัสที่อธิบายทำให้ฟังดูเหมือนว่ากำลังตรวจสอบมากกว่า 89 ในขณะที่รหัสของคุณผ่านกรณีทดสอบดังนั้นจึงมีการตรวจสอบอย่างถูกต้องมากกว่า 90
trichoplax

1
ฉันแก้ไขคำอธิบายแล้ว แต่ฉันเขียนว่า "cast to integer" เนื่องจากฉันไม่แน่ใจว่าผู้ปฏิบัติงานควรปฏิบัติอย่างไรต่อค่าทศนิยมที่เป็นลบ ไม่มีปัญหาที่นี่เพราะมันทำงานได้กับค่าสัมบูรณ์ แต่ฉันไม่ชอบการตั้งสมมติฐานที่แข็งแกร่งเกินไปสำหรับผู้ประกอบการ
Osable

1
คุณสามารถแทนที่v"NESW"yk})ด้วยÇ30^5%:)
Adnan

5

Python 3, 146 145 117 107 97 94 93 92 ไบต์

f(s):u='NESW'.find(s[0])*90;return(u+f(s[1:]))/2+180*(abs(u-‌​f(s[1:]))>180)if s[1:]else u

โทรfด้วยสายอักขระ


คุณไม่สามารถมีสองตัวที่...0elseพวกเขาขว้างไปได้ SyntaxErrors
Jonathan Allan

@JonathanAllan คุณใช้ Python เวอร์ชันใดอยู่ ฉันใช้งาน 3.5.2 ได้
L3viathan

ฉันวิ่งไปที่ 3.3.3 - คุณสามารถลบช่องว่างระหว่างelseและ-ด้วยหรือไม่ (สามารถใน 3.3.3)
Jonathan Allan

@JanathanAllan ใช่ฉันทำได้! ขอบคุณที่ช่วยฉันอีกไบต์
L3viathan

2
@Titus d.findสามารถฉันมีความคิดที่แน่นอนในนาทีที่ผ่านมา; ดูคำตอบที่อัปเดต
L3viathan

5

C, 184 ไบต์

double h(char c){return ((c=='E')+(c=='S')*2+(c=='W')*3);}double d(char*s){double f=h(*s);if(s[1]){double t=f;f=(f+d(s+1)/90)/2;if(((t-f)>1)||((f-t)>1))f+=2;if(f>=4)f-=4;}return f*90;}

Ungolfed

// a helper function
double direction_(char ch)
{
    if (ch=='N')
        return 0.;
    else if (ch=='E')
        return 90.;
    else if (ch=='S')
        return 180.;
    else
        return 270.;
}

// this is the main function to call
double direction(char* str)
{
    double fAngle = direction_(str[0]);
    if (str[1])
    {
        double tmp = fAngle + direction(str+1);
        if (tmp>=360.)
            tmp-=360.;
        tmp/=2;

        if (((tmp-fAngle)>90.) || ((tmp-fAngle)<-90.))
        { //  check if we need to take the "other side"; if the resulting angle is more than 90 degrees away, we took the wrong on
            if (tmp>=180.)
                tmp-=180.;
            else
                tmp+=180.;
        }
        fAngle = tmp;
    }
    return fAngle;
}

ดูเหมือนว่าการใช้โฟลตไม่ได้ให้ความแม่นยำกับคุณ
Eyal Lev

4
ยินดีต้อนรับสู่ PPCG! : D
mbomb007

ชื่อของฟังก์ชั่นจะไม่ขัดแย้งกัน (เนื่องจากชื่อทั้งคู่d)?
clismique

@qwerp, ลายเซ็นที่แตกต่างกัน (อันเดียวใช้ตัวถ่าน *, ตัวอื่นใช้ตัวอักษรเท่านั้น)
Eyal Lev

2
ชื่อฟังก์ชั่นไม่ได้ชื่อ mangled ใน C เช่นเดียวกับใน C ++ ดังนั้นคุณจำเป็นต้องเปลี่ยนชื่อหนึ่งในนั้นถ้าคุณต้องการให้มันเป็น C
Klas Lindbäck

3

R, 172 146 ไบต์

z=rev((0:3*90)[match(scan(,""),c("N","E","S","W"))]);p=z[1];l=length(z);for(i in 2:l)p=(p+z[i])/2+(abs(p-z[i])>180)*180;if(l<2)p=z;sprintf("%f",p)

Ungolfed

z=rev((0:3*90)[match(scan,""),c("N","E","S","W"))]); #1
p=z[1];                                              #2
l=length(z)                                          #3
for(i in 2:l)p=(p+z[i])/2+(abs(p-z[i])>180)*180;     #4
if(l<2)p=z                                           #5
sprintf("%f",p)                                      #6

อธิบาย

  1. อ่านอินพุตจาก stdin
    • จับคู่อินพุตตามดัชนีกับ c("N","E","S","W")
    • จากดัชนีที่จับคู่: จับคู่กับเวกเตอร์องศา0:3*90(แทนc(0,90,180,270))
    • ย้อนกลับและเก็บเป็น z
  2. เริ่มต้นpให้เทียบเท่ากับระดับสุดท้ายในการป้อนข้อมูล
  3. เก็บความยาวของอินพุตเป็น l
  4. ให้คำนวณแบริ่งที่แบ่งเป็นสองส่วนที่ใกล้เคียงที่สุด
  5. หากกำหนดอินพุตเพียงหนึ่งค่าให้ตั้งpเป็นz
  6. รูปแบบและพิมพ์

ลองกรณีทดสอบบนซอ - ปริศนา (โปรดทราบว่านี่เป็นฟังก์ชั่นเนื่องจากscanไม่ทำงานบนซอ - ซอ


โดยที่ผลลัพธ์นั้นถูกต้องเป็นทศนิยม 5 ตำแหน่งคุณไม่จำเป็นต้องทำการปัดเศษ จากการท้าทาย: Outputs 0.00001 and 0.000005 are both correct.ดังนั้นคุณควรจะสามารถบันทึกไบต์โดยไม่ปัดเศษ
trichoplax

@trichoplax ฉันเข้าใจ อินพุตสามารถเป็นเวกเตอร์ของอักขระสตริงได้ไหม c("N","N","E")แทน"NNE"? ["N","N","E"]เทียบเท่ากับรายการหลามที่ไม่ซ้อนกันนี้
Billywob

ใช่. ฉันตั้งใจ "ลำดับ" เป็นคำทั่วไปเพื่อรวมสิ่งต่าง ๆ เช่นอาร์เรย์เวกเตอร์รายการสิ่งอันดับ
trichoplax

1
ฉันคิดว่าคุณสามารถบันทึกได้ 4 ไบต์หากคุณหารทุกอย่างด้วย 90 และพิมพ์ (p * 90)
ติตัส

3

Haskell, 109 105 103 ไบต์

h=180
a#b|abs(a-b)<h=n|n>h=n-h|1>0=n+h where n=(a+b)/2 -- calculates the new "mean" on the cirlce
f 'N'=0                                          -- translates characters to angles
f 'E'=90
f 'S'=h
f _=270
foldr1(#).map f                                  -- traverses the whole string

ขอบคุณสำหรับ -2 byte @xnor!


รายการครบถ้วนสมบูรณ์สำหรับfดูยาว แต่ฉันมีปัญหาในการค้นหาสิ่งที่สั้นกว่า ที่ใกล้ที่สุดที่ฉันได้รับคือf c=90*until(\i->"NESW"!!i==c)(+1)0(35) ฉันคิดว่าคุณสามารถแทนที่ด้วย'W' _
xnor

ใช่ฉันก็คาดว่าจะมีบางสิ่งที่สั้นกว่านี้ แต่ไม่พบสิ่งใดเลย ขอบคุณสำหรับ_!
ข้อบกพร่อง

3

Dyalog APL , 55 45 38 ไบต์

วิธีการแก้

ต้องการ⎕IO←0ซึ่งเป็นค่าเริ่มต้นในหลาย ๆ ระบบ ขอทิศทาง

360|÷○÷180×12○(+÷(|+))/¯12○○2÷⍨'NES'⍳⍞

คำอธิบาย

ไปแก้ไขปัญหาด้วยการแปลงตัวอักษรแต่ละตัวไปยังหมายเลขที่ซับซ้อน1∠ θ ⇔ + ข·ฉันแล้วทำผลรวมลดลงจากขวาไปซ้าย (มือขวาของ APL) ในขณะที่ normalizing ในแต่ละขั้นตอน สุดท้ายθจะถูกแปลงแล้วองศาและปกติจะต้องอยู่ภายใน [0, 360):

'NES'⍳⍞ดัชนีของจดหมายป้อนข้อมูลแต่ละตัวใน "NES" N → 0, E → 1, S → 2, อะไรก็ได้→ 3

○2÷⍨แปลงเป็นมุมเป็นเรเดียน θ = π · x2

¯12○แปลงเป็นจำนวนเชิงซ้อนบนวงกลมหน่วย e i ·θ

(... )/ลดรายการด้วย ... (เช่นแทรกฟังก์ชันระหว่างองค์ประกอบของ ... )

+÷(|+)... ผลรวมปกติ x n - 1 + x n| x n - 1 + x n |

12○แปลงเป็นมุม θ

÷○÷180×แปลงเป็นองศา 1 / π · 1 / 180 · x

360| ส่วนที่เหลือเมื่อหารด้วย 360

ลองใช้ออนไลน์!

เกร็ดพงศาวดาร

ถ้าอินพุทและเอาท์พุทเป็นหน่วยที่ซับซ้อนฉากวิธีแก้ปัญหาทั้งหมดจะเป็นเพียงแค่:

(+÷(|+))/

ส่วนที่เหลือของรหัสคือการแยกวิเคราะห์อินพุตและเอาต์พุตการจัดรูปแบบ


ฉันสังเกตเห็นว่าผลการทดสอบไม่ตรงกับสิ่งที่ท้าทายถึงทศนิยม 5 ตำแหน่งทำให้สิ่งนี้ไม่ถูกต้อง Dyalog APL มีตัวเลือกในการใช้ความแม่นยำสองเท่าหรือไม่?
trichoplax

@trichoplax ใช่⎕FR←1287ใช้ประโยชน์จาก 128 บิตลอย แต่ TryAPL ไม่อนุญาต
59

ฉันคิดว่าอะไรที่มากกว่าหรือเท่ากับ 64 บิตลอยควรใช้งานได้ (ฉันได้ทดสอบเฉพาะใน Python เท่านั้น) นี่หมายความว่าคุณสามารถทำให้รหัสถูกต้อง แต่จะใช้ได้กับผู้ที่ติดตั้งภาษาเท่านั้น บางทีคุณอาจแสดงรหัสที่ถูกต้องแบบเต็มสำหรับคะแนนและรวมถึงเวอร์ชันออนไลน์ที่ไม่ค่อยมีความแม่นยำที่จำเป็นเพื่อให้ผู้คนเห็นว่าอัลกอริทึมนั้นถูกต้อง
trichoplax

@trichoplax ที่จริงแล้ว TryAPL ใช้ความแม่นยำสองเท่า แต่กรณีทดสอบของคุณมีข้อผิดพลาดเกิน 53 บิต
59

หากสามารถแสดงให้เห็นว่าความแตกต่างนั้นเกิดจากความแตกต่างในการตีความมาตรฐาน IEEE 754 ที่ยังคงเป็นไปตามมาตรฐานฉันจะปรับกรณีทดสอบเพื่อให้แน่ใจว่าการตีความทั้งสองให้ผลลัพธ์เดียวกันกับทศนิยม 5 ตำแหน่ง ฉันเลือกกรณีทดสอบเพื่อให้ผลลัพธ์เหมือนกับทศนิยม 5 ตำแหน่งใน Python สำหรับทั้งทศนิยม (ความแม่นยำสองเท่า) และทศนิยมความแม่นยำโดยพลการ ฉันจะดูมัน
trichoplax

2

เสียงกระเพื่อมสามัญ347 327 ไบต์

ขอบคุณ @Titus ที่สละเวลาสักครู่

สิ่งนี้อาจจะเล่นกอล์ฟได้มากกว่า แต่อย่างน้อยก็ใช้งานได้ (ฉันคิดว่า):

(defun d(c)(if(eql c #\N)0(if(eql c #\E)1(if(eql c #\S)2(if(eql c #\W)3)))))(defun m(a b)(if(> a b)(rotatef a b))(if(<(+(- 4 b)a)(- b a))(+(/(+(- 4 b)a)2)b)(+(/(- b a)2)a)))(defun f(s)(let((c))(setf c(d(char s(1-(length s)))))(do((a)(p(-(length s)2)(1- p)))((< p 0))(setf a(char s p))(setf c(m(d a)c)))(format t"~5$"(* c 90))))

การใช้งาน:

* (f "WNE")
337.50000
NIL

ฟังก์ชั่นdใช้เวลาตัวละครN, E, WหรือSและผลตอบแทนการศึกษาระดับปริญญาที่เหมาะสม ฟังก์ชั่นmจะได้รับการรวมระดับของสองทิศทางที่ได้รับการอนุมัติ ฟังก์ชั่นfวนซ้ำผ่านสตริงที่มีให้คำนวณระดับที่เหมาะสมและพิมพ์เป็นจุดลอย


เสียงกระเพื่อมของฉันเป็นสนิม แต่สามารถหารทุกอย่างโดย 90 บันทึก 6 ไบต์?
ติตัส

@Titus ฉันคิดว่ามันจะ ฉันได้ตระหนักถึงการปรับปรุงอื่น ๆ ดังนั้นฉันจะเพิ่มสิ่งนี้เมื่อฉันอยู่ที่คอมพิวเตอร์ของฉัน
artificialnull

2

Befunge, 183 181 175 ไบต์

>~#+:#25#%6*#/`#2_$>5%4*:00p"Z}"4*:***20g#v_+2/00g10g-:8`\0\-8`+!v
v5:+*:*:"d"/+55+5$_^#!:\p01/**:*4"}Z":p020<%**:*"(2Z"+**5*:*"0}"!<
>5>+#<%#56#58#:*#/+\#5:#5_$$$,,,".">:#,_@

ลองออนไลน์!

คำอธิบาย

สิ่งนี้ตามอัลกอริธึมที่คล้ายกันกับคำตอบอื่น ๆ อีกมากมายมีเพียงการใช้การคำนวณจุดคงที่ที่จำลองด้วยจำนวนเต็มเนื่องจาก Befunge ไม่สนับสนุนจุดลอย

ขอบคุณ@Titusสำหรับรูทีน ASCII-to-int

 ~ : 5 6* ` _$        while ((c = getchar()) > 30)  // ends with any ctrl char or EOF
> + 2 %6 / 2            push(c / 2 % 6 + 2)         // partial conversion to int

                      do {
  5%                    dir = pop() % 5             // completes the conversion to int   
  4*:00p                dir *= 4; lowres_dir = dir  // used by the 180-flip calculation
  "Z}"4*:***            dir *= 22500000             // this is 90000000 / 4 
  20g_                  if (!first_pass) {
    +2/                   dir = (dir+last_dir)/2    // last_dir is second item on stack
    00g10g-               diff = lowres_dir - last_lowres_dir
    :8`\0\-8`+!!          flip = diff>8 || -diff>8
    "}0"*:*5**+           dir += flip * 180000000   // add 180 degrees if we need to flip
    "Z2("*:**%            dir %= 360000000          // keep within the 360 degree range
                        }
  020p                  first_pass = false
  :"Z}"4*:**/10p        last_lowres_dir = dir / 22500000
  \                     last_dir = dir              // saved as second item on stack
  :!_                 } while (!stack.empty())

$                     pop()                         // this leaves the final dir on top
5+55+/                dir = (dir + 5)/10            // round down to 5 decimal places
"d":*:*+              dir += 100000000              // add a terminating digit
                      while (true) {                // convert into chars on stack
:55 + % 6 8 * +\ : _    push(dir%10+'0'); if (!dir) break
   > < 5 5 : /+ 5 5     dir /= 10
                      }

$$$                   pop() x 3                     // drop the chars we don't need
,,,                   putchar(pop()) x 3            // output first three chars
"."                   push('.')                     // add a decimal point
>:#,_@                while(c=pop()) putchar(c)     // output the remaining chars

นั่นหมายความว่าคุณจำเป็นต้องจำลองประเภทจุดคงที่ที่มีขนาดใหญ่กว่า (ตำแหน่งทศนิยมมากขึ้น) หรือไม่? กรณีทดสอบได้รับการออกแบบมาเพื่อต้องการความแม่นยำสองเท่าซึ่งไม่เกิน 17 ตัวเลขสำคัญ (สูงสุด 16 ตำแหน่งทศนิยม) และ 14 ตำแหน่งทศนิยมอาจเพียงพอ
trichoplax

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