พื้นที่ผิวของจัตุรมุข


16

ความท้าทาย

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

คุณสามารถสมมติว่าทั้งสี่คะแนนจะแตกต่างกันและจะได้รับผ่าน STDIN 1 จุดต่อบรรทัด แต่ละจุดจะประกอบด้วยจำนวนเต็ม 16 บิตที่ไม่ได้ลงชื่อ รูปแบบที่แน่นอนของแต่ละจุดสามารถแก้ไขได้ถ้ามันทำให้สิ่งต่าง ๆ ง่ายขึ้นเช่นจำนวนเต็มสามช่องว่างคั่น อย่างไรก็ตามการมีจุดแต่ละจุดในบรรทัดแยกต่างหาก ผลลัพธ์ควรผ่าน STDOUT ไปที่ตำแหน่งทศนิยมอย่างน้อย 2 ตำแหน่ง

สำหรับผู้ที่ไม่ทราบว่าจัตุรมุขเป็นของแข็งสามมิติที่เกิดขึ้นจากใบหน้ารูปสามเหลี่ยม 4 หน้า

ตัวอย่าง

# input (format is up to you, see clarification above)
[23822, 47484, 57901]
[3305, 23847, 42159]
[19804, 11366, 14013]
[52278, 28626, 52757]

# output
2932496435.95

โปรดทิ้งข้อความไว้ถ้าคุณสังเกตเห็นว่าคณิตศาสตร์ของฉันผิด


@BetaDecay ไม่ความคิดก็คือพวกเขาจะได้รับการป้อนผ่าน STDIN ในสี่บรรทัดแยก ฉันจะแก้ไขคำถามเพื่อให้ความกระจ่าง
stokastic

อินพุตสามารถเป็นได้[[list],[of],[lists]]หรือไม่?
ฟอสจีน

@phosgene ฉันชอบคิดว่าการอ่านอินพุตเป็นส่วนหนึ่งของความท้าทายดังนั้นฉันจะบอกว่าไม่ ฉันจะพยายามผ่อนปรนข้อมูลจำเพาะอินพุตให้มากขึ้นในความท้าทายในอนาคต
stokastic

นี่คือจัตุรมุขปกติหรือผิดปกติหรือไม่?
James Williams

@JamesWilliams ตัวอย่างที่โพสต์ผิดปกติ โปรแกรมของคุณควรจัดการกับอินพุตใด ๆ รวมถึงจัตุรมุขปกติ
stokastic

คำตอบ:


5

Python, 198 178 161 ตัวอักษร

V=eval('input(),'*4)
A=0
for i in range(4):F=V[:i]+V[i+1:];a,b,c=map(lambda e:sum((a-b)**2for a,b in zip(*e)),zip(F,F[1:]+F));A+=(4*a*b-(a+b-c)**2)**.5
print A/4

รูปแบบการป้อนข้อมูลจะได้รับในคำถาม

มันจะคำนวณความยาวของขอบติดกันของใบหน้าแล้วใช้สูตรของนกกระสา


4

Matlab / Octave 103

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

%input
[23822, 47484, 57901;
3305, 23847, 42159;
19804, 11366, 14013;
52278, 28626, 52757]



%actual code
c=input('');
a=0;
for i=1:4;
    d=c;d(i,:)=[];
    d=d(1:2,:)-[1 1]'*d(3,:);
    a=a+norm(cross(d(1,:),d(2,:)))/2;
end
a

แต่ละจุดจะต้องป้อนในบรรทัดแยกต่างหากเป็นอินพุตมาตรฐาน
DavidC

ฉันแรกคิดว่าไม่มีสิ่งเช่นอินพุตมาตรฐานใน Matlab แต่ฉันค้นพบฟังก์ชั่นที่สามารถใช้ในการจำลองสิ่งนี้ผ่านทางหน้าต่างคำสั่งดังนั้นตอนนี้คุณสามารถส่งผ่านอินพุตได้ตามภาษาอื่น
ข้อบกพร่อง

น่าสนใจ นั่นเป็นคำสั่งเดียวกับที่ Mathematica ใช้Input[]
DavidC

ทำไมคุณถึงคิดว่าสิ่งนี้น่าสนใจ? ดูเหมือนว่า 'อินพุต' ของฉันจะเหมือนกับชื่อสามัญที่ค่อนข้างใช้กับฟังก์ชันที่ทำสิ่งนี้
ข้อบกพร่อง

จนกระทั่งเมื่อวานนี้ผมไม่ทราบจริงๆสิ่งที่ "เข้ามาตรฐาน" ความหมายและผมคิดว่า Mathematica ไม่ได้มี "มาตรฐาน" การป้อนข้อมูลแม้ว่าฉันได้ใช้เป็นประจำInput[], InputString[], และImport[] ImportString[]
DavidC

4

APL, 59

f←{+.×⍨⊃1 2-.⌽(⊂⍵)×1 2⌽¨⊂⍺}
.5×.5+.*⍨(f/2-/x),2f/4⍴x←⎕⎕⎕-⊂⎕

ทำงานโดยการคำนวณผลิตภัณฑ์ข้าม

คำอธิบาย
บรรทัดแรกกำหนดฟังก์ชั่นที่รับสองอาร์กิวเมนต์ (ชื่อ implicity และ) โดยปริยายคาดว่าพวกมันจะเป็นอาร์เรย์ที่มีความยาวเป็นตัวเลข 3 ถือว่ามันเป็นเวกเตอร์ 3 มิติและคำนวณขนาดกำลังสองของผลิตภัณฑ์ครอสของพวกเขา

                        ⊂⍺   # Wrap the argument in a scalar
                   1 2⌽¨     # Create an array of 2 arrays, by rotating `⊂⍺` by 1 and 2 places
             (⊂⍵)×           # Coordinate-wise multiply each of them with the other argument
        1 2-.⌽               # This is a shorthand for:
        1 2  ⌽               #   Rotate the first array item by 1 and the second by 2
           -.                #   Then subtract the second from the first, coordinate-wise
       ⊃                     # Unwrap the resulting scalar to get the (sorta) cross product
   +.×                       # Calculate the dot product of that...
      ⍨                      # ...with itself
f←{+.×⍨⊃1 2-.⌽(⊂⍵)×1 2⌽¨⊂⍺} # Assign function to `f`

บรรทัดที่สองทำส่วนที่เหลือ

                         ⎕⎕⎕-⊂⎕ # Take 4 array inputs, create an array of arrays by subtracting one of them from the other 3
                       x←        # Assign that to x
                     4⍴          # Duplicate the first item and append to the end
                  2f/            # Apply f to each consecutive pair
            2-/x                 # Apply subtraction to consecutive pairs in x
          f/                     # Apply f to the 2 resulting arrays
         (f/2-/x),2f/4⍴x←⎕⎕⎕-⊂⎕ # Concatenate to an array of 4 squared cross products
   .5+.*⍨                        # Again a shorthand for:
   .5  *⍨                        #   Take square root of each element (by raising to 0.5)
     +.                          #   And sum the results
.5×                              # Finally, divide by 2 to get the answer

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

@flawr ฉันมักจะทำเช่นนั้นเพราะการเล่นกอล์ฟใน APL ส่วนใหญ่มาจากการออกแบบอัลกอริทึมและเป็นไปได้มากที่สุดที่จะทำให้เกิดปัญหาที่ไม่ธรรมดา แต่ฉันรู้สึกเหมือน "การคำนวณข้ามผลิตภัณฑ์" บ่งบอกถึงอัลกอริทึมที่นี่มากพอ หากคุณต้องการคำอธิบายแบบเต็มฉันจะทำมันในวันนี้
TwiNight

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

3

Python 3, 308 298 292 279 258 254

from itertools import*
def a(t,u,v):w=(t+u+v)/2;return(w*(w-t)*(w-u)*(w-v))**.5
z,x,c,v,b,n=((lambda i,j:(sum((i[x]-j[x])**2for x in[0,1,2]))**.5)(x[0],x[1])for*x,in combinations([eval(input())for i in">"*4],2))
print(a(z,x,v)+a(z,c,b)+a(b,v,n)+a(x,c,n))

สิ่งนี้ใช้:

  • ทฤษฎีบทพีทาโกรัส (ในรูปแบบ 3 มิติ) เพื่อกำหนดความยาวของแต่ละบรรทัด
  • สูตรของเฮรอนเพื่อหาพื้นที่ของสามเหลี่ยมแต่ละอัน

1
ฉันใช้วิธีเดียวกันสำหรับทดสอบวิธีแก้ปัญหาของฉัน ฉันจะลองเล่นกอล์ฟของฉันและโพสต์ในภายหลัง
stokastic

1
คุณfor i in">"*4เป็นคนฉลาด
stokastic

คุณสามารถเขียนโค้ดที่มีความยาว 3 ตัวได้แทนที่จะใช้ len (i) ในฟังก์ชันพิสัยของคุณ
stokastic

1
คุณสามารถบันทึกตัวอักษรไม่กี่ทำรากที่เป็นแทนx**0.5 math.sqrt(x)
Snorfalorpagus

1
คุณสามารถบันทึกไบต์ที่สองโดยการวางในหนึ่งบรรทัดเช่นดังนั้น:def a(t,u,v) def a(t,u,v):w=(t+u+v)/2;return(w*(w-t)*(w-u)*(w-v))**0.5
Beta Decay

2

Mathematica 168 154

สิ่งนี้จะค้นหาความยาวของขอบของจัตุรมุขและใช้สูตรของเฮรอนเพื่อกำหนดพื้นที่ของใบหน้า

t = Subsets; p = Table[Input[], {4}];
f@{a_, b_, c_} := Module[{s = (a + b + c)/2}, N[Sqrt[s (s - #) (s - #2) (s -#3)] &[a, b, c], 25]]
  Tr[f /@ (EuclideanDistance @@@ t[#, {2}] & /@ t[p, {3}])]

มีเส้นทางที่ตรงกว่าที่ต้องการเพียง60 ตัวอักษรเท่านั้น แต่มันละเมิดกฎตราบเท่าที่มันคำนวณพื้นที่ของใบหน้าแต่ละหน้าด้วยฟังก์ชั่นในตัวArea:

p = Table[Input[], {4}];
N[Tr[Area /@ Polygon /@ Subsets[p, {3}]], 25]

1

ปราชญ์ - 103

print sum((x*x*y*y-x*y*x*y)^.5for x,y in map(differences,Combinations(eval('vector(input()),'*4),3)))/2

ส่วนการป้อนข้อมูลอ่านดัดแปลงมาจากคำตอบของคี ธ แรนดัล


0

Python - 260

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

import copy,math
P=[input()for i in"1234"]
def e(a, b):return math.sqrt(sum([(b[i]-a[i])**2 for i in range(3)]))
o=0
for j in range(4):p=copy.copy(P);p.pop(j);a,b,c=[e(p[i],p[(i+1)%3])for i in range(3)];s=(a+b+c)/2;A=math.sqrt(s*(s-a)*(s-b)*(s-c));o+=A
print o

มันใช้ขั้นตอนเดียวกับ laurencevs


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

เคล็ดลับ: คุณสามารถบันทึกตัวละครบางตัวr=rangeได้ จะสั้นกว่าlambda จะถูกแทนที่ด้วย สามารถลงไป ใช้เพียงครั้งเดียว defmath.sqrt(…)**.5p=copy.copy(P);p.pop(j);p=P[:j-1]+P[j:]A
Wrzlprmft

0

C, 303

ไม่รวมช่องว่างที่ไม่จำเป็น อย่างไรก็ตามยังมีสนามกอล์ฟอีกมากที่ต้องทำที่นี่ (ฉันจะพยายามกลับมาทำในภายหลัง) มันเป็นครั้งแรกที่ฉันได้ประกาศforวนรอบใน#defineวงในฉันได้พบวิธีที่จะลดจำนวนลูปมาก่อนเสมอ

ผมต้องเปลี่ยนจากfloatการdoubleจะได้คำตอบเช่นเดียวกับ OP สำหรับกรณีทดสอบ ก่อนหน้านั้นมันคือ 300 รอบ

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

#define F ;for(i=0;i<12;i++)
#define D(k) (q[i]-q[(i+k)%12])
double q[12],r[12],s[4],p,n;

main(i){
  F scanf("%lf",&q[i])
  F r[i/3*3]+=D(3)*D(3),r[i/3*3+1]+=D(6)*D(6)
  F r[i]=sqrt(r[i])
  F i%3||(s[i/3]=r[(i+3)%12]/2),s[i/3]+=r[i]/2
  F i%3||(p=s[i/3]-r[(i+3)%12]),p*=s[i/3]-r[i],n+=(i%3>1)*sqrt(p)   
  ;printf("%lf",n);       
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.