Calcular o volume de um objeto


18

Você pode determinar o volume de objetos com base em um determinado conjunto de dimensões:

  • O volume de uma esfera pode ser determinado usando um único número, o raio ( r)
  • O volume de um cilindro pode ser determinado usando dois números, o raio ( r) e a altura ( h)
  • O volume de uma caixa pode ser determinado usando três números, comprimento ( l), largura ( w) e altura ( h)
  • O volume de uma pirâmide triangular irregular pode ser determinado usando quatro números, os comprimentos laterais ( a, b, c) e a altura ( h).

O desafio é determinar o volume de um objeto, com uma das seguintes entradas:

  • Um único número (r)ou (r, 0, 0, 0)=>V = 4/3*pi*r^3
  • Dois números (r, h)ou (r, h, 0, 0)=>V = pi*r^2*h
  • Três números (l, w, h)ou (l, w, h, 0)=>V = l*w*h
  • Quatro números (a, b, c, h)=> V = (1/3)*A*h, onde Aé dado pela fórmula de Heron :A = 1/4*sqrt((a+b+c)*(-a+b+c)*(a-b+c)*(a+b-c))

Regras e esclarecimentos:

  • A entrada pode ser números inteiros e / ou decimais
  • Você pode assumir que todas as dimensões de entrada serão positivas
  • Se Pi é codificado deve ser preciso até: 3.14159.
  • A saída deve ter pelo menos 6 dígitos significativos, exceto os números que podem ser representados com precisão com menos dígitos. Você pode produzir 3/4como 0.75, mas 4/3deve ser 1.33333(mais dígitos estão OK)
    • Como arredondar valores imprecisos é opcional
  • O comportamento para entrada inválida é indefinido
  • Regras padrão para E / S. A entrada pode ser uma lista ou argumentos separados

Isso é código de golfe, então a solução mais curta em bytes vence.

Casos de teste:

calc_vol(4)
ans =  268.082573106329

calc_vol(5.5, 2.23)
ans =  211.923986429533

calc_vol(3.5, 4, 5)
ans =  70

calc_vol(4, 13, 15, 3)
ans =  24

Relacionado, mas diferente .


1
A ordem das dimensões precisa ser a ordem indicada na pergunta?
Mego


@Mego, você pode escolher ...
Stewie Griffin

@StewieGriffin Varargs e obter matrizes de tamanho dinâmico é uma dor no meu idioma (pelo menos para mim, um iniciante). Posso fornecer quatro funções para lidar com cada contagem de argumentos?
cat

Você pode ter uma matriz de tamanho fixo com os últimos elementos definidos como zero, se necessário. Isso deve cobrir, eu acho? Ou você pode sobrecarregar funções como na resposta Haskell. Você não pode ter funções diferentes com nomes diferentes.
Stewie Griffin

Respostas:


4

MATL , 57 53 51 44 bytes

3^4*3/YP*GpG1)*YP*GpG0H#)ts2/tb-p*X^3/*XhGn)

A entrada é uma matriz com 1, 2, 3 ou 4 números.

Experimente online!

Explicação

Em vez de usar ifloops aninhados , que são caros em termos de bytes, isso calcula quatro resultados possíveis para qualquer entrada e escolhe o resultado apropriado, dependendo do comprimento da entrada.

Ao calcular os resultados, mesmo que apenas um deles precise ser válido, os outros não podem cometer erros. Isso significa, por exemplo, que a indexação do quarto elemento da entrada não é permitida, porque a entrada pode ter menos de quatro elementos.

                    % take input implicitly
3^4*3/YP*           % compute a result which is valid for length-1 input:
                    % each entry is raised to 3 and multiplied by 4/3*pi
G                   % push input
pG1)*YP*            % compute a result which is valid for length-2 input:
                    % product of all entries, times first entry, times pi
G                   % push input
p                   % compute a result which is valid for length-3 input:
                    % product of all entries
G                   % push input
0H#)ts2/tb-p*X^3/*  % compute a result which is valid for length-4 input:
                    % shorter version of Heron's formula applied on all
                    % entries except the last, times last entry, divided by 3
Xh                  % collect all results in a cell array
G                   % push input
n)                  % pick appropriate result depending on input length
                    % display implicitly

Que versão da fórmula de Heron você está usando?
Addison Crump #

@CoolestVeto Aquele com o semiperímetro. Primeira fórmula a partir daqui
Luis Mendo

Bem feito @DonMuesli. Eu consegui-lo usando "apenas" 34 bytes mais em MATLAB =)
Stewie Griffin

9

Vitsy, 49 bytes

Eu pensei que você me entregou este em um prato, mas achei um bug não resolvido para contornar. Não me machucou, no entanto.

lmN
3^43/*P*
2^*P*
**
v:++2/uV3\[V}-]V3\*12/^v*3/

Basicamente, com a entrada tendo um certo comprimento para diferentes funções, você me fornece minha sintaxe de método para fazer essas coisas. Então, sim, sucesso!

Explicação, uma linha de cada vez:

lmN
l   Get the length of the stack.
 m  Go to the line index specified by the top item of the stack (the length).
  N Output as a number.

3^43/*P*
3^
          Put to the power of 3.
  43/*    Multiply by 4/3.
      P*  Multiply by π

2^*P*
2^     Put to the second power.
  *    Multiply the top two items.
   P*  Multiply by π

**
**     Multiply the top three items of the stack.

v:++2/uV3\[V}-]V3\*12/^v*3/
v                            Save the top item as a temp variable.
 :                           Duplicate the stack.
  ++                         Sum the top three values.
    2/                       Divide by two.
      u                      Flatten the top stack to the second to top.
       V                     Capture the top item of the stack (semiperimeter) 
                             as a permanent variable.
        3\[   ]              Do the stuff in the brackets 3 times.
           V}-               Subtract the semiperimeter by each item.
               V             Push the global var again.
                3\*          Multiply the top 4 items.
                   12/^      Square root.
                       v*    Multiply by the temp var (the depth)
                         3/  Divide by three.

A entrada é aceita como argumentos de linha de comando no reverso exato, conforme aparecem na pergunta, sem zeros à direita.

Experimente online!

Como um aparte, aqui está algo que está atualmente em desenvolvimento.

Pacote Java com Vitsy

Observe que este pacote está em andamento; isto é apenas para mostrar como isso funcionará no futuro (a documentação para isso ainda não foi carregada) e não é jogada no golfe, e é uma tradução literal:

import com.VTC.vitsy;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;

public class Volume {
    public static void main(String[] args) {
        Vitsy vitsyObj = new Vitsy(false, true);
        vitsyObj.addMethod(new Vitsy.Method() {
            public void execute() {
                vitsyObj.pushStackLength();
                vitsyObj.callMethod();
                vitsyObj.outputTopAsNum();
            }
        });
        vitsyObj.addMethod(new Vitsy.Method() {
            public void execute() {
                vitsyObj.push(new BigDecimal(3));
                vitsyObj.powerTopTwo();
                vitsyObj.push(new BigDecimal(4));
                vitsyObj.push(new BigDecimal(3));
                vitsyObj.divideTopTwo();
                vitsyObj.multiplyTopTwo();
                vitsyObj.pushpi();
                vitsyObj.multiplyTopTwo();
            }
        });
        vitsyObj.addMethod(new Vitsy.Method() {
            public void execute() {
                vitsyObj.push(new BigDecimal(2));
                vitsyObj.powerTopTwo();
                vitsyObj.multiplyTopTwo();
                vitsyObj.pushpi();
                vitsyObj.multiplyTopTwo();
            }
        });
        vitsyObj.addMethod(new Vitsy.Method() {
            public void execute() {
                vitsyObj.multiplyTopTwo();
                vitsyObj.multiplyTopTwo();
            }
        });
        vitsyObj.addMethod(new Vitsy.Method() {
            public void execute() {
                vitsyObj.tempVar();
                vitsyObj.cloneStack();
                vitsyObj.addTopTwo();
                vitsyObj.addTopTwo();
                vitsyObj.push(new BigDecimal(2));
                vitsyObj.divideTopTwo();
                vitsyObj.flatten();
                vitsyObj.globalVar();
                vitsyObj.push(new BigDecimal(3));
                vitsyObj.repeat(new Vitsy.Block() {
                    public void execute() {
                        vitsyObj.globalVar();
                        vitsyObj.rotateRight();
                        vitsyObj.subtract();
                    }
                });
                vitsyObj.globalVar();
                vitsyObj.push(new BigDecimal(3));
                vitsyObj.repeat(new Vitsy.Block() {
                    public void execute() {
                        vitsyObj.multiplyTopTwo();
                    }
                });
                vitsyObj.push(new BigDecimal(1));
                vitsyObj.push(new BigDecimal(2));
                vitsyObj.divideTopTwo();
                vitsyObj.powerTopTwo();
                vitsyObj.tempVar();
                vitsyObj.multiplyTopTwo();
                vitsyObj.push(new BigDecimal(3));
                vitsyObj.divideTopTwo();
            }
        });
        vitsyObj.run(new ArrayList(Arrays.asList(args)));
    }
}

1
Definitivamente a ferramenta certa para o trabalho
Mego

5

C, 100 97 bytes

#define z(a,b,c,d) d?d*sqrt(4*a*a*b*b-pow(a*a+b*b-c*c,2))/12:c?a*b*c:3.14159*(b?a*a*b:4/3.*a*a*a)

editar 1: remover decimal desnecessário ., obrigado Immibis!


2
Não pode 4./3.ser apenas 4/3.? E pode 2.e 12.apenas ser 2e 12?
precisa saber é o seguinte

Você está absolutamente correto. Obrigado!
Josh

4

JavaScript ES6, 129 126 125 116 114 90 bytes

Economizei muitos bytes (9) com uma fórmula maravilhosa, graças a Stewie Griffin! Como a entrada deve ser diferente de zero, variable?será suficiente para uma verificação de definição.

with(Math){(a,b,c,h,Z=a*a)=>h?sqrt(4*Z*b*b-(D=Z+b*b-c*c)*D)/4:c?a*b*c:b?PI*Z*b:4/3*PI*Z*a}

Teste!

with(Math){Q = (a,b,c,h,Z=a*a)=>h?sqrt(4*Z*b*b-(D=Z+b*b-c*c)*D)/4:c?a*b*c:b?PI*Z*b:4/3*PI*Z*a}
console.log = x => o.innerHTML += x + "<br>";

testCases = [[4], [5.5, 2.23], [3.5, 4, 5], [4, 13, 15, 3]];
redo = _ => (o.innerHTML = "", testCases.forEach(A => console.log(`<tr><td>[${A.join(", ")}]` + "</td><td> => </td><td>" + Q.apply(window, A) + "</td></tr>")));
redo();
b.onclick = _ => {testCases.push(i.value.split(",").map(Number)); redo();}
*{font-family:Consolas,monospace;}td{padding:0 10px;}
<input id=i><button id=b>Add testcase</button><hr><table id=o></table>


5
Com matemática? Parece legítimo.
Addison Crump #

Este erros no Chrome 48, Uncaught SyntaxError: Unexpected token =(referindo-se Z=a*a)
Patrick Roberts

@PatrickRoberts Use o Firefox. Ele permite parâmetros padrão dentro de lambdas.
Conor O'Brien #

Parece que não consigo fazer a versão 4-arg funcionar ... e você nunca usa o valor de h, o que parece um pouco de supervisão.
314 Neil

@ Neil Huh, é verdade. Vou precisar ver essa fórmula novamente, Stewie excluiu seu comentário ...
Conor O'Brien

3

Haskell, 114 109 107 101 99 bytes

v[r]=4/3*pi*r^3
v[r,h]=pi*r^2*h
v[x,y,z]=x*y*z
v[a,b,c,h]=h/12*sqrt(4*a^2*b^2-(a^2+b^2-c^2)^2)

Pega uma lista de números e retorna um volume. Chame como

v[7]

para uma esfera, etc. A função é polimórfica para qualquer tipo que implemente sqrt(então, basicamente Floatou Double).

Não vai ganhar nenhum concurso por brevidade. Mas observe como é legível . Mesmo se você realmente não conhece Haskell, pode dizer o que faz com bastante facilidade. A sintaxe de correspondência de padrões de Haskell facilita muito a definição de funções estranhas que fazem algo totalmente diferente dependendo da forma da entrada.


1
(1/3)*(1/4)*h,,, por que não h/12? Economiza muitos bytes!
Stewie Griffin

1
Além disso, a variante do eq de Heron que Conor usa parece ser muito menor.
Stewie Griffin

@StewieGriffin Aparentemente sim. : -}
MathematicsOrchid

Haskell é legível apenas para infix math, que eu não acho legível. Então você entra .e #e $torna-se Sopa Mathematica.
cat

3

PowerShell, 165 161 bytes

param($a,$b,$c,$h)((($h/12)*[math]::Sqrt(($a+$b+$c)*(-$a+$b+$c)*($a-$b+$c)*($a+$b-$c))),(($a*$b*$c),((($p=[math]::PI)*$b*$a*$a),($p*$a*$a*$a*4/3))[!$b])[!$c])[!$h]

Então ... Muitos ... Dólares ... (31 dos 161 caracteres representam $19,25% do código) ... mas salvou 4 bytes graças a Stewie Griffin!

Tomamos quatro entradas e depois indexamos progressivamente em declarações pseudo-ternárias com base nelas em ordem inversa. Por exemplo, o exterior (..., ...)[!$h]testa se a quarta entrada está presente. Nesse caso, a !$hvontade é igual 0e a primeira metade é executada (o volume de uma pirâmide irregular triagonal). Caso contrário, !$hcom $h = $null(como não inicializado) será igual 1, então ele vai para a segunda metade, que por si só é um pseudo-ternário baseado [!$c]e assim por diante.

Provavelmente, isso é quase ideal, já que a fórmula supostamente mais curta que (por exemplo) Cᴏɴᴏʀ O'Bʀɪᴇɴ está usando é na verdade 2 bytes a mais no PowerShell, graças à falta de um ^operador ... A única economia real advinda do (1/3)*(1/4)*A*$hgolfe A*$h/12e configuração $pposterior para salvar alguns bytes em vez da [math]::PIchamada longa .


1

CJam, 67 66 bytes

q~0-_,([{~3#4*P*3/}{~\_**P*}{:*}{)\a4*(a\[1W1]e!..*+::+:*mq*C/}]=~

Vou trabalhar para encurtá-lo em breve. Experimente online !

Explicação para vir.


1

Sério, 65 59 55 bytes

`kd@;Σ½╗"╜-"£Mπ╜*√*3@/``kπ``ª*╦*``3;(^/4*╦*`k,;lD(E@i(ƒ

Experimente online!

Explicação

Este é um doozy. Vou dividir a explicação em várias partes.

Corpo Principal:

`...``...``...``...`k,;lD(E@i(ƒ
`...``...``...``...`k            push 4 functions to a list
                     ,;lD        push input, len(input)-1
                         (E      get the function at index len(input)-1
                           @i(   flatten the input list
                              ƒ  execute the function

Função 0:

3;(^/4*╦*
3;(^       push 3, r^3
    /      divide (r^3/3)
     4*    multiply by 4 (4/3*r^3)
       ╦*  multiply by pi (4/3*pi*r^3)

Função 1:

ª*╦*
ª     r^2
 *    multiply by h (r^2*h)
  ╦*  multiply by pi (pi*r^2*h)

Função 2:

kπ  listify, product (l*w*h)

Função 3 (21 bytes; quase metade do comprimento do programa!)

kd@;Σ½╗"╜-"£Mπ╜*√*3@/
kd@                    listify, dequeue h, bring [a,b,c] back on top
   ;Σ½                       dupe, sum, half (semiperimeter)
      ╗                push to register 0
       "╜-"£M          map: push s, subtract (s-x for x in (a,b,c))
             π         product
              ╜*√      multiply by s, sqrt (Heron's formula for area of the base)
                 *3@/  multiply by h, divide by 3 (1/3*A*h)

1

Matlab, 78 bytes

@(a,b,c,d)pi*a^2*(4/3*a*~b+b*~c)+a*b*c*~d+d/12*(4*a^2*b^2-(a^2+b^2-c^2)^2)^.5;

Certamente não pode ficar mais curto que isso. ~b, ~ce ~d, são 0se cada uma das dimensões for diferente de zero. Uma fórmula com uma dimensão zero dará apenas zero. Dessa forma, cada uma das fórmulas pode ser simplesmente resumida. Não ife elseobrigatório.

Chame assim (ou tente online aqui ):

g=@(a,b,c,d)pi*a^2*(4/3*a*~b+b*~c)+a*b*c*~d+d/12*(4*a^2*b^2-(a^2+b^2-c^2)^2)^.5;

g(4,0,0,0)
ans =  268.082573106329

g(5.5,2.23,0,0)
ans =  211.923986429533

g(3.5,4,5,0)
ans =  70

g(4,13,15,3)
ans =  24

1
Que loucura de variáveis :-) Sim, isso parece difícil de encurtar mais longe
Luis Mendo

Talvez adicione um link para experimentá-lo online? ideone.com/6VZF9z
Luis Mendo

0

Python 3 2, 127 119 116 bytes

Agradecemos a alguém e à Mego por toda sua ajuda no golfe. Agradeço também a Cᴏɴᴏʀ O'Bʀɪᴇɴ e Josh quando peguei emprestadas partes de suas respostas por essa.

def v(a,b,c,d):z=a*a;P=3.14159;print filter(int,[max(0,(4*z*b*b-(z+b*b-c*c)**2))**.5*d/12,a*b*c,P*z*b,P*z*a*4/3])[0]

Ungolfed:

def v(a, b, c, d):
    z = a*a
    p = 3.14159
    s = filter(int,[max(0,(4*z*b*b-(z+b*b-c*c)**2))**.5*d/12,a*b*c,P*z*b,P*z*a*4/3])
    print s[0]

Jogou mais: def v(a,b,c,d):z=a*a;p=355/113;return[x for x in[(4*z*b*b-(z+b*b-c*c)**2)**.5*d/12,a*b*c,p*z*b,p*z*a*4/3]if x][0]assumindo que a entrada é preenchida com 0s.
somente ASCII

Além disso, se você usar o Python 2, poderá fazê-lodef v(a,b,c,d):z=a*a;P=3.14159;return filter(int,[(4*z*b*b-(z+b*b-c*c)**2)**.5*d/12,a*b*c,P*z*b,P*z*a*4/3])[0]
somente ASCII

0

Mathematica, 114 (103)

Função pura: 114

Which[(l=Length@{##})<2,4.Pi/3#1^3,l<3,#1^2.Pi#2,l<4,#1#2#3,l<5,(4#1^2#2^2-(#1^2+#2^2-#3^2)^2)^.5#4/12]~Quiet~All&

Ungolfed:

fun = Which[
  (l = Length@{##}) < 2,
    4. Pi/3 #1^3,
  l < 3,
    #1^2 Pi #2, 
  l < 4,
    #1 #2 #3, 
  l < 5,
    (4 #1^2 #2^2 - (#1^2 + #2^2 - #3^2)^2)^.5 #4/12
]~Quiet~All &

Uso:

fun[4]
268.083
fun[5.5, 2.23]
211.924
fun[3.5, 4, 5]
70.
fun[4, 13, 15, 3]
24.

Se funções nomeadas forem permitidas: 103

f[r_]:=4.Pi/3r^3
f[r_,h_]:=r^2.Pi h
f[l_,w_,h_]:=l w h
f[a_,b_,c_,h_]:=(4a^2b^2-(a^2+b^2-c^2)^2)^.5h/12

Uso:

f[4]
268.083
f[5.5, 2.23]
211.924
f[3.5, 4, 5]
70.
f[4, 13, 15, 3]
24.

1
#1==#, Eu acho Quiet[x_]:=Quiet[x,All]e π (Alt-P em um Mac) se encaixa em ASCII estendido.
CalculatorFeline

Você não pode substituir #1 #2 #3com 1##? Não se esqueça#==#1
CalculatorFeline

0

Fator, 783 bytes

Bem, isso levou uma eternidade.

USING: arrays combinators io kernel locals math math.constants math.functions quotations.private sequences sequences.generalizations prettyprint ;
: 1explode ( a -- x y ) dup first swap 1 tail ;
: 3explode ( a -- b c d ) 1explode 1explode 1explode drop ;
: spr ( r -- i ) first 3 ^ 4 3 / pi * swap * ;
: cyl ( r -- i ) 1explode 1explode drop 2 ^ pi swap * * ; : cub ( v -- i ) 1 [ * ] reduce ;
: A ( x a -- b d ) reverse dup dup dup 0 [ + ] reduce -rot 3explode neg + + -rot 3explode - + 3array swap 3explode + - 1array append 1 [ * ] reduce sqrt .25 swap * ;
: ilt ( a -- b c  ) V{ } clone-like dup pop swap A 1 3 / swap pick * * ;
: volume ( v -- e ) dup length { { [ 1 = ] [ spr ] } { [ 2 = ] [ cyl ] } { [ 3 = ] [ cub ] } { [ 4 = ] [ ilt ] } [ "bad length" throw ] } cond print ;

Ligue { array of numbers } volume.


@ StewieGriffin: O PI esqueceu totalmente de encurtar os nomes das funções. Não vai ajudar muito, no entanto.
cat
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.