Jakie są moje wymiary?

18

Zadanie: Biorąc pod uwagę obszar trójkąta, znajdź trójkąt Heroński z tym obszarem. Dowolny trójkąt heroński o określonym obszarze jest dozwolony.

Trójkąt Heroński to trójkąt z bokami liczb całkowitych i obszarem liczb całkowitych . Według wzoru Herona trójkąt o długości boków a,b,cma powierzchnię

sqrt(s*(s-a)*(s-b)*(s-c))

gdzie s=(a+b+c)/2jest połowa obwodu trójkąta. Można to również zapisać jako

sqrt((a+b+c)*(-a+b+c)*(a-b+c)*(a+b-c)) / 4

Jeśli taki trójkąt nie istnieje, dane wyjściowe mają stałą wartość falsey.

Dane wejściowe: Pojedyncza dodatnia liczba całkowita reprezentująca obszar trójkąta.

Wyjście: dowolne trzy długości boków dla takiego trójkąta LUB fałszywa wartość.

Przykłady:

Input -> Output
6 -> 3 4 5
24 -> 4 15 13
114 -> 37 20 19
7 -> error

Obowiązują standardowe luki

To jest kod golfowy, wygrywa najkrótsza odpowiedź w bajtach.

Neil A.
źródło
6
Czy potrafisz napisać stosunkowo zwięzłą definicję trójkąta herońskiego w swoim wyzwaniu?
Okx,
1
@Okx: Czy nie jest jasne, że jest to trójkąt z bokami liczb całkowitych i obszarem liczb całkowitych?
Neil A.,
@Okx: To jest pomysł. Wystarczy, że znajdziesz jeden taki przykład dla danego obszaru, jeśli istnieje.
Neil A.,
Z linku do Wikipedii: „Trójkąt Heroński jest trójkątem o długości boku i powierzchni, które są liczbami całkowitymi”.
Neil A.,
5
Czy możesz wyjaśnić, co jest mylące w definicji w pytaniu?
Neil A.,

Odpowiedzi:

6

Galaretka , 17 16 bajtów

-1 bajt dzięki Erikowi outgolferowi (skorzystaj z szybkiego, ¥)

SHð;_P
ṗ3Ç⁼¥Ðf²Ḣ

Zastosowanie formuły Herona metodą brutalnej siły.

Wypróbuj online! (osiągalimit60 lat dla przypadku testu 114. Zajmuje lokalnie 3m 30s - sprawdza 114 3 = 1 481 544 trójek)

W jaki sposób?

Prawdziwe rozwiązanie do gry w golfa - biorąc pod uwagę obszar a, znajduje wszystkie krotki trzech liczb całkowitych pomiędzy 1i a(nawet z powtarzającymi się trójkątami i te bez obszaru), pobiera ich obszar i filtruje dla tych z pożądanym obszarem (nawet nie zatrzymuje się, gdy tylko jeden zostaje znaleziony, przebija je wszystkie i potem wyskakuje pierwszy wynik) Daje, 0jeśli nie istnieje.

SHð;_P - Link 1, get the square of the area of a triangle: list of sides
S      - sum the sides (get the perimeter)
 H     - halve
  ð    - dyadic chain separation (call that p)
    _  - subtraction (vectorises) =    [p-side1,  p-side2,  p-side3]
   ;   - concatenate              = [p, p-side1,  p-side2,  p-side3]
     P - product                  =  p*(p-side1)*(p-side2)*(p-side3)
                                  = the square of Heron's formula = area squared

ṗ3Ç⁼¥Ðf²Ḣ - Main link: number a (area)
ṗ3        - third Cartesian power (all triples of [1,area] : [[1,1,1],[1,1,2],[1,2,1],[1,2,2],[2,1,1],[2,1,2],[2,2,1],[2,2,2], ... ,[a,a,a]]
       ²  - square a
     Ðf   - filter keep if:
    ¥     -   last two links as a dyad:
  Ç       -     call last link (1) as a monad f(list of sides)
   ⁼      -     left (that result) equals right (square of a)?
        Ḣ - head - get the first one (an empty list yields 0, perfect for the falsey case)
Jonathan Allan
źródło
Pomyślałem, że ktoś spróbuje to brutalnie wykorzystać, miło!
Neil A.,
@NeilA. Wyobrażam sobie, że większość zgłoszeń do gry w golfa będzie brutalna dla tego wyzwania - ale niektórym uda się zagrać w golfa, będąc mniej absurdalnie nieefektywnym niż to.
Jonathan Allan
Można wymienić çz Ç⁼¥i zdjąć drugą linię w całości.
Erik the Outgolfer
@EriktheOutgolfer Och, dzięki, zastanawiałem się, jak sobie z tym poradzić ...
Jonathan Allan
5

JavaScript (ES7), 109 102 100 98 bajtów

Zwraca tablicę 3 liczb całkowitych lub false. Podobnie jak odpowiedź Jelly , jest to brutalne wymuszanie formuły Herona.

A=>[...Array(A**3)].some((_,a)=>A*A/(r=[b=a/A%A|0,c=a/A/A|0,a%=A],p=a+b+c>>1)/(p-a)/(p-b)==p-c)&&r

Przypadki testowe


Wersja rekurencyjna, 83 bajty

Zwraca tablicę 3 liczb całkowitych lub zgłasza błąd rekurencji. Niestety działa tylko w przypadku niewielkich nakładów.

f=(A,n)=>A*A/(r=[a=n%A,b=n/A%A|0,c=n/A/A|0],p=a+b+c>>1)/(p-a)/(p-b)==p-c?r:f(A,-~n)

Próbny

Arnauld
źródło
4

Haskell , 69 bajtów

f a=take 1[t|t<-mapM(\_->[1..a])":-)",a*a==product[sum t/2-x|x<-0:t]]

Wypróbuj online!

Generuje singleton listy trzech trójkątów takich jak [[3.0,4.0,5.0]]. Niemożliwe dane wejściowe dają []. Technicznie Falsejest to tylko Falsey dla Haskell, ale ponieważ Haskell wymaga, aby wszystkie możliwe dane wyjściowe były tego samego typu, nie można go użyć. Jeśli błąd może być użyty jako Falsey, [...]!!0zaoszczędziłby 3 bajty take 1[..].

Próbuje wszystkich trzech tmożliwych długości boków, począwszy od 1obszaru a. Formuła Herona służy do sprawdzania, czy obszar pasuje przez (s-0)(s-x)(s-y)(s-z)==a*agdzie s=(x+y+z)/2jest sum t/2. Produkt(s-0)(s-x)(s-y)(s-z) jest wyrażany jako productz elementami wziętymi z 0:t, tj. Potrójny, a także 0.

xnor
źródło
+1 za uśmiechniętą twarz, nawet jeśli jest to trochę noop
Julian Wolf
2

F #, 170 156 152 bajtów

let f(a,b,c)=
 let s=(a+b+c)/2.0
 s*(s-a)*(s-b)*(s-c)
let g A=[for a in 1.0..A do for b in a..A do for c in b..A do yield a,b,c]|>List.find(f>>(=)(A*A))

Wypróbuj online!

„Niegolfowany”

let calculateArea (a, b, c) =
    let s = (a+b+c)/2.0
    s*(s-a)*(s-b)*(s-c)

let getTriangle A =
    [  for a in 1.0..A do
       for b in a..A do
       for c in b..A do yield a,b,c
    ]
    |> List.find(calculateArea>>(=)(A * A))

Jeśli nie zostaną znalezione żadne wyniki, program się zepsuje. Jeśli nie jest to pożądane, muszę zamienić List.findna List.filter(+2 bajty), które utworzą pustą listę w przypadku, gdy nic nie zostanie znalezione, lub List.tryFind(+3 bajty), zwracając Brak w przypadku braku trójkąta.

Zawsze uważam, że golfowa wersja F # jest nadal dość czytelna.

Brunner
źródło
1
Nie znam F #, ale wyobrażam sobie, że możesz zrezygnować z System.Math.Sqrti porównać wynikową wartość A * A?
Sean
@Sean Oczywiście! Dzięki za podpowiedź :)
Brunner
Zastąpienie 1.0..A [...] 1.0..A [...] 1.0..Aprzez 1.0..A [...] a..A [..] b..Apowinno zaoszczędzić kilka bajtów i nieco przyspieszyć (jeśli to działa; Mam bardzo minimalne doświadczenie w F #).
97 CAD
@ CAD97 To robi! Dzięki za zwrócenie na to uwagi.
Brunner
2

Python 2 (PyPy) , 131 123 118 bajtów

n=input()
t=n*3;r=i=c=0
while c<t:
 i+=1;a,b,c=i%t,i/t%t,i/t/t;s=a+b+c>>1
 if(s-a)*s*(s-b)*(s-c)==n**2:r=a,b,c
print r

Wypróbuj online!

Chociaż działa to również na CPython, PyPy jest znacznie szybszy i jest w stanie obliczyć trójkąt dla 114 w limicie czasu na TIO.

Czasy z mojej maszyny:

$ echo 114 | time pypy2 d.py
        0.55 real         0.52 user         0.02 sys
$ echo 114 | time python2 d.py
       52.46 real        51.76 user         0.27 sys
ovs
źródło
1

Pyth - 23 bajty

/mu*G-/sd2Hd/sd2^UQ3^Q2

Który drukuje wartość prawda / fałsz, lub

fq^Q2u*G-/sT2HT/sT2^UQ3

który drukuje wszystkie możliwe rozwiązania i jest strasznie wolny przy dużych nakładach. Wpisz „h” na początku, aby wydrukować tylko jeden.

Wyjaśnienie:

fq^Q2u*G-/sT2HT/sT2^UQ3
                    UQ    # List of numbers from 0 to input-1
                   ^  3   # All triples of these numbers
f                         # Filter this by the following test (on variable T, based on Hero's formula)
     u*G-/sT2HT/sT2       # s*(s-a)*(s-b)*(s-c), where s is the sum of the triple over 2 (calclated as /sT2 )
 q^Q2                     # Test if equal to input ^2

Spróbuj

Maria
źródło
1

Perl 6 , 54 bajtów

->\a{first {a*a==[*] .sum/2 «-«(0,|$_)},[X] ^a xx 3}

Brute force szukaj wszystkich możliwych stron do jednego mniej niż aobszar wejściowy.

  • ^ato zakres liczb od 0 do a - 1.
  • [X] ^a xx 3zmniejsza, w zależności od produktu, trzy kopie tego zakresu, tworząc wszystkie trojaczki od (0, 0, 0)do (a - 1, a - 1, a - 1).
  • Szukamy firsttrojaczki tak, aby pole trójkąta z tymi bokami było równe a, z wykorzystaniem wzoru Herona .

W obrębie bloku kodu podanego dla first:

  • $_jest trojaczką. Nazwij to (x, y, z)tutaj.
  • (0,|$_)jest taka sama, ale tryplet 0poprzedzany: (0, x, y, z).
  • .sum / 2jest połową obwodu (ilość, która jest nazywana sw zwykłym wyrażeniu wzoru Herona).
  • .sum / 2 «-« (0, |$_)hiperoperator odejmowania z spo lewej i (0, x, y, z)po prawej stronie, daje (s - 0, s - x, s - y, s - z).
  • [*] następnie zmniejsza ten kwadruplet z pomnożeniem, dając kwadrat obszaru.
  • a * a == szuka kwadratu równego kwadratowi danego obszaru.

Jeśli nie zostanie znaleziony triplet, Nil(który jest falsey) jest zwracany.

Sean
źródło
1

Haskell , 76 bajtów

f s=[[a,b,c]|a<-[1..s],b<-[1..a],c<-[1..b],a*a*c*c-(a*a+c*c-b*b)^2/4==4*s*s]

Spowoduje to wyświetlenie listy list zawierającej wszystkie możliwe całkowite rozmiary, które generują poprawny obszar za pomocą brutalnej siły (generując pustą listę, jeśli nie ma). Zastrzeżenie polega na tym, że powoduje ich podwojenie z powodu tego podziału na środku, ale ich część ułamkowa jest zawsze równa 0.

Jeśli z jakiegoś powodu nie możesz tego znieść,

f s=[[a,b,c]|a<-[1..s],b<-[1..a],c<-[1..b],4*a*a*c*c-(a*a+c*c-b*b)^2==16*s*s]

Spowoduje to wyświetlenie odpowiedzi w postaci listy liczb całkowitych dla 89 77 bajtów łącznie lub 13 1 dodatkowych bajtów. (Dzięki Neil)

Jeśli potrzebujesz / chcesz tylko pierwszego elementu, po prostu umieszczenie go !!0na końcu da ci tylko pierwszy element, jeśli są liczby, które mają zastosowanie, i błąd, jeśli nie będzie żadnych 3 kolejnych bajtów, a take 1na początku zabierze pierwszy element bez pomyłki dla Jeszcze 6 bajtów.

Wypróbuj online!

Sierżant Doggo
źródło
Jeśli chcesz uniknąć dublowania, nie możesz po prostu pomnożyć równania przez 4 z każdej strony?
Neil
0

TI-Basic, 70 69 bajtów

Prompt A
For(B,1,A
For(C,1,B
For(D,1,C
(B+C+D)/2
If A2=Ansprod(Ans-{B,C,D
Then
Disp B,C,D
Return
End
End
End
End
/

Wyświetla trzy długości boków, jeśli jest trójkąt, zgłasza błąd składniowy, jeśli go nie ma (dzięki /na końcu).

-1 bajt dzięki komentarzowi Seana do innej odpowiedzi

pizzapanty184
źródło
0

Mathematica, 77 bajtów

z Mathematica's Solve

s=(a+b+c)/2;d=Sqrt[s(s-a)(s-b)(s-c)];Solve[d==#&&0<a<b<c<#,{a,b,c},Integers]&

Mathematica, 117 bajtów

brutalna siła

s=(a+b+c)/2;l="error";(For[a=1,a<#,a++,For[b=1,b<a,b++,For[c=1,c<b,c++,If[Sqrt[s(s-a)(s-b)(s-c)]==#,l={a,b,c}]]]];l)&
J42161217
źródło
1
Mathematica nie ma wbudowanego? Zaskakujący.
Neil A.
@ovs, możesz też zaoszczędzić na tym jeden bajt Area@SSSTriangle[a,b,c].
numbermaniac
0

Właściwie 22 bajty

;╗R3@∙⌠;Σ½;)♀-π*╜²=⌡░F

Wypróbuj online!

Wyjaśnienie:

;╗R3@∙⌠;Σ½;)♀-π*╜²=⌡░F  (implicit input: A)
;╗                      store a copy of A in register 0
  R                     range(1, A+1)
   3@∙                  ternary Cartesian product (all triples with values in [1, A])
      ⌠;Σ½;)♀-π*╜²=⌡░   filter: take triples where function returns truthy
       ;Σ½                make a copy of the triple, compute s = (a+b+c)/2
          ;)              make a copy of s, move it to the bottom of the stack
            ♀-            subtract each value in the triple from s
              π*          product of those values and s (s*(s-a)*(s-b)*(s-c))
                ╜²        A*A
                  =       compare equality (does area of triangle with given dimensions equal input?)
                     F  take first triple that satisfies the filter (or empty list if none)
Mego
źródło
0

Casio Basic, 123 bajty

For 1⇒a To n
For 1⇒b To n
For 1⇒c To n
If(s*(s-a)*(s-b)*(s-c)|s=(a+b+c)/2)=n^2
Then
Print{a,b,c}
Stop
IfEnd
Next:Next:Next

Standardowe rozwiązanie brutalnej siły. 122 bajty dla kodu, 1 bajt do określenia njako parametr.

NumberManiac
źródło