Écrivez une fonction qui prend (x, y) et ramène x à la puissance de y SANS boucles [fermé]


14

Il s'agit d'un court défi vraiment soigné.

Ecrire une fonction ou d' une procédure qui prend deux paramètres, xet yet renvoie le résultat de SANS utiliser des boucles ou des fonctions intégrées de puissance.xy

Le gagnant est la solution la plus créative et sera choisi en fonction du plus grand nombre de votes après 3 jours.


1
De quel genre de défi s'agit-il?
VisioN

22
Et alors exp(log(x)*y)?
r3mainer

2
Une réponse pour les nombres entiers est-elle uniquement acceptable? Puisque ce sont les premières réponses.
mmumboss

4
On dirait que les réponses jusqu'à présent utilisent la récursivité ou des listes de «x» répétés. Je suis en train de me casser la tête en essayant de penser à une autre façon (en particulier quelque chose qui permet un y non entier).
BenM

1
Malheureusement, l'interdiction des boucles exclut les solutions mathématiques amusantes comme l'expansion de Taylor.
shadowtalker

Réponses:


27

APL (7)

{×/⍵/⍺}

L'argument de gauche est la base, l'argument de droite est l'exposant, par exemple:

     5 {×/⍵/⍺} 6
15625

Explication:

  • ⍵/⍺reproduit les temps, par exemple 5 {⍵/⍺} 6->5 5 5 5 5 5
  • ×/prend le produit, par exemple ×/5 5 5 5 5 5-> 5×5×5×5×5×5->15625

2
Hm .. Cela peut être écrit en 5 caractères en J, exactement la même méthode. */@$~
seequ

@Sieg 4 même, si vous autorisez l'exposant à gauche, la base à droite.
ɐɔıʇǝɥʇuʎs

J'ai eu l'adverbe flip parce que je pensais que ce n'était pas permis.
seequ

@Seeq 4 à Dyalog APL :×/⍴⍨
Adám

27

C #: exposants en virgule flottante

OK, cette solution est assez fragile. Vous pouvez facilement le casser en y jetant des nombres ridiculement gros comme 6. Mais cela fonctionne à merveille pour des choses comme DoublePower(1.5, 3.4), et n'utilise pas la récursivité!

    static double IntPower(double x, int y)
    {
        return Enumerable.Repeat(x, y).Aggregate((product, next) => product * next);
    }

    static double Factorial(int x)
    {
        return Enumerable.Range(1, x).Aggregate<int, double>(1.0, (factorial, next) => factorial * next);
    }

    static double Exp(double x)
    {
        return Enumerable.Range(1, 100).
            Aggregate<int, double>(1.0, (sum, next) => sum + IntPower(x, next) / Factorial(next));
    }

    static double Log(double x)
    {
        if (x > -1.0 && x < 1.0)
        {
            return Enumerable.Range(1, 100).
                Aggregate<int, double>(0.0, (sum, next) =>
                    sum + ((next % 2 == 0 ? -1.0 : 1.0) / next * IntPower(x - 1.0, next)));
        }
        else
        {
            return Enumerable.Range(1, 100).
                Aggregate<int, double>(0.0, (sum, next) =>
                    sum + 1.0 / next * IntPower((x - 1) / x, next));
        }
    } 

    static double DoublePower(double x, double y)
    {
        return Exp(y * Log(x));
    } 

43
"des nombres ridiculement énormes comme 6" J'ai aimé ça.
DavidC

Sûrement, l'utilisation des fonctions Enumerable repose sur le bouclage qui était interdit dans la question ou est-ce correct parce que la boucle est à l'intérieur des méthodes du framework?
Chris

16

C ++

Que diriez-vous d'une programmation de méta modèle? Cela détourne le peu de règles, mais ça vaut le coup:

#include <iostream>


template <int pow>
class tmp_pow {
public:
    constexpr tmp_pow(float base) :
        value(base * tmp_pow<pow-1>(base).value)
    {
    }
    const float value;
};

template <>
class tmp_pow<0> {
public:
    constexpr tmp_pow(float base) :
        value(1)
    {
    }
    const float value;
};

int main(void)
{
    tmp_pow<5> power_thirst(2.0f);
    std::cout << power_thirst.value << std::endl;
    return 0;
}

1
mais ce n'est pas une fonction, c'est une valeur au moment de la compilation, n'est-ce pas? : O
PaperBirdMaster

Eh bien, un constructeur est une fonction, et les paramètres du modèle sont presque comme des arguments de fonction ... non? =)
erlc

@PaperBirdMaster Ouais ... c'est pourquoi j'ai admis une certaine flexion des règles. Je pensais que j'allais soumettre quelque chose en plus de la récursion de queue, mais je viens de soumettre la récursion de queue de compilation, haha. Assez proche cependant, non?
astephens4

@ astephens4 assez près, j'adore: 3
PaperBirdMaster

15

Python

def power(x,y):
    return eval(((str(x)+"*")*y)[:-1])

Ne fonctionne pas pour les pouvoirs non entiers.


J'aime celui la.
CodyBugstein

1
Pourquoi ajoutez-vous un séparateur sans l' utiliser join? eval('*'.join([str(x)] * y)).
Bakuriu

1
Était-ce à la traîne?
gerrit

Je voudrais également noter que python a l' **opérateur, donc vous pourriez avoir eval () d cela.
Riking

3
@Riking: ce serait une fonction intégrée, cependant.
Hovercouch

10

Haskell - 25 caractères

f _ 0=1
f x y=x*f x (y-1)

Après la version APL de Marinus:

f x y = product $ take y $ repeat x

Avec le commentaire de mniip et les espaces supprimés, 27 caractères:

f x y=product$replicate y x

utiliser replicate y xau lieu detake y $ repeat x
mniip

4
J'étais convaincu que vous pouviez sauver des caractères en écrivant votre deuxième fonction sans point. Il s'avère que f=(product.).flip replicatec'est exactement le même nombre de caractères.
Kaya

@mniip Ce n'est pas grave, ce n'est pas du golf de code.
nyuszika7h

10

Python

Si yest un entier positif

def P(x,y):
    return reduce(lambda a,b:a*b,[x]*y)

7

JavaScript (ES6), 31

// Testable in Firefox 28
f=(x,y)=>eval('x*'.repeat(y)+1)

Usage:

> f(2, 0)
1
> f(2, 16)
65536

Explication:

La fonction ci-dessus construit une expression qui se multiplie x ypuis l'évalue.


6

Je suis surpris de voir que personne n'a encore écrit de solution avec le Y Combinator ... ainsi:

Python2

Y = lambda f: (lambda x: x(x))(lambda y: f(lambda v: y(y)(v)))
pow = Y(lambda r: lambda (n,c): 1 if not c else n*r((n, c-1)))

Pas de boucles, pas d'opérations vectorielles / liste et pas de récursivité (explicite)!

>>> pow((2,0))
1
>>> pow((2,3))
8
>>> pow((3,3))
27

Uh, I've just seen right now KChaloux's Haskell solution that uses fix, upvoting him...
berdario

5

C# : 45

Works for integers only:

int P(int x,int y){return y==1?x:x*P(x,y-1);}

Beat me to it :-) I think you could save a few bytes by writing return --y?x:x*P(x,y); instead
r3mainer

1
But this isn't code-golf...
Oberon

1
@oberon winning criteria was not clear when this was posted. Things have moved on.
Level River St

@steveverrill Sorry.
Oberon

Also in C# --y would be an int which is not the same as a bool like in other languages.
Chris

5

bash & sed

No numbers, no loops, just an embarrasingly dangerous glob abuse. Preferably run in an empty directory to be safe. Shell script:

#!/bin/bash
rm -f xxxxx*
eval touch $(printf xxxxx%$2s | sed "s/ /{1..$1}/g")
ls xxxxx* | wc -l
rm -f xxxxx*

"Preferably run in an empty directory to be safe." :D
Almo

5

Javascript

function f(x,y){return ("1"+Array(y+1)).match(/[\,1]/g).reduce(function(l,c){return l*x;});}

Uses regular expressions to create an array of size y+1 whose first element is 1. Then, reduce the array with multiplication to compute power. When y=0, the result is the first element of the array, which is 1.

Admittedly, my goal was i) not use recursion, ii) make it obscure.


5

Mathematica

f[x_, y_] := Root[x, 1/y]

Probably cheating to use the fact that x^(1/y) = y√x


Not cheating. Smart.
Michael Stern

This is brilliant. Wish I'd thought of it for my R post.
shadowtalker


4

Golfscript, 8 characters (including I/O)

~])*{*}*

Explanation:

TLDR: another "product of repeated array" solution.

The expected input is two numbers, e.g. 2 5. The stack starts with one item, the string "2 5".

Code     - Explanation                                             - stack
                                                                   - "2 5"
~        - pop "2 5" and eval into the integers 2 5                - 2 5        
]        - put all elements on stack into an array                 - [2 5]
)        - uncons from the right                                   - [2] 5
*        - repeat array                                            - [2 2 2 2 2]
{*}      - create a block that multiplies two elements             - [2 2 2 2 2] {*}
*        - fold the array using the block                          - 32

Golfscript is always the way to go.
Nit

3

Ruby

class Symbol
  define_method(:**) {|x| eval x }
end

p(:****[$*[0]].*(:****$*[1]).*('*'))

Sample use:

$ ruby exp.rb 5 3
125
$ ruby exp.rb 0.5 3
0.125

This ultimately is the same as several previous answers: creates a y-length array every element of which is x, then takes the product. It's just gratuitously obfuscated to make it look like it's using the forbidden ** operator.


3

C, exponentiation by squaring

int power(int a, int b){
    if (b==0) return 1;
    if (b==1) return a;
    if (b%2==0) return power (a*a,b/2);
    return a*power(a*a,(b-1)/2);
}

golfed version in 46 bytes (thanks ugoren!)

p(a,b){return b<2?b?a:1:p(a*a,b/2)*(b&1?a:1);}

should be faster than all the other recursive answers so far o.O

slightly slower version in 45 bytes

p(a,b){return b<2?b?a:1:p(a*a,b/2)*p(a,b&1);}

1
For odd b, ~-b/2 == b/2.
ugoren

@ugoren oh sure, you're right
izabera

This is a popular interview question :) "How can you write pow(n, x) better than O(n)?"
Jordan Scales

3

Haskell - 55

pow x y=fix(\r a i->if i>=y then a else r(a*x)(i+1))1 0

There's already a shorter Haskell entry, but I thought it would be interesting to write one that takes advantage of the fix function, as defined in Data.Function. Used as follows (in the Repl for the sake of ease):

ghci> let pow x y=fix(\r a i->if i>=y then a else r(a*x)(i+1))1 0
ghci> pow 5 3
125

2

Q

9 chars. Generates array with y instances of x and takes the product.

{prd y#x}

Can explicitly cast to float for larger range given int/long x:

{prd y#9h$x}

1
Matching Golfscript in length is a feat to achieve.
Nit

2

Similar logic as many others, in PHP:

<?=array_product(array_fill(0,$argv[2],$argv[1]));

Run it with php file.php 5 3 to get 5^3


2

I'm not sure how many upvotes I can expect for this, but I found it somewhat peculiar that I actually had to write that very function today. And I'm pretty sure this is the first time any .SE site sees this language (website doesn't seem very helpful atm).

ABS

def Rat pow(Rat x, Int y) =
    if y < 0 then
        1 / pow(x, -y)
    else case y {
        0 => 1;
        _ => x * pow(x, y-1);
    };

Works for negative exponents and rational bases.

I highlighted it in Java syntax, because that's what I'm currently doing when I'm working with this language. Looks alright.


2

Pascal

The challenge did not specify the type or range of x and y, therefore I figure the following Pascal function follows all the given rules:

{ data type for a single bit: can only be 0 or 1 }
type
  bit = 0..1;

{ calculate the power of two bits, using the convention that 0^0 = 1 }
function bitpower(bit x, bit y): bit;
  begin
    if y = 0
      then bitpower := 1
      else bitpower := x
  end;

No loop, no built-in power or exponentiation function, not even recursion or arithmetics!


2

J - 5 or 4 bytes

Exactly the same as marinus' APL answer.

For x^y:

*/@$~

For y^x:

*/@$

For example:

   5 */@$~ 6
15625
   6 */@$ 5
15625

x $~ y creates a list of x repeated y times (same as y $ x

*/ x is the product function, */ 1 2 3 -> 1 * 2 * 3


1

Python

from math import sqrt

def pow(x, y):
    if y == 0:
        return 1
    elif y >= 1:
        return x * pow(x, y - 1)
    elif y > 0:
        y *= 2
        if y >= 1:
            return sqrt(x) * sqrt(pow(x, y % 1))
        else:
            return sqrt(pow(x, y % 1))
    else:
        return 1.0 / pow(x, -y)

1
** is built-in operator imo.
Silviu Burcea

@SilviuBurcea True, editing.
Oberon

@SilviuBurcea operator =/= function
VisioN

@VisioN true, but the idea was about built-ins. I don't think the OP knows about all these built-in operators ...
Silviu Burcea

1

Javascript

With tail recursion, works if y is a positive integer

function P(x,y,z){z=z||1;return y?P(x,y-1,x*z):z}

1

Bash

Everyone knows bash can do whizzy map-reduce type stuff ;-)

#!/bin/bash

x=$1
reduce () {
    ((a*=$x))
}
a=1
mapfile -n$2 -c1 -Creduce < <(yes)
echo $a

If thats too trolly for you then there's this:

#!/bin/bash

echo $(( $( yes $1 | head -n$2 | paste -s -d'*' ) ))

1

C

Yet another recursive exponentiation by squaring answer in C, but they do differ (this uses a shift instead of division, is slightly shorter and recurses one more time than the other):

e(x,y){return y?(y&1?x:1)*e(x*x,y>>1):1;}

1

Mathematica

This works for integers.

f[x_, y_] := Times@@Table[x, {y}]

Example

f[5,3]

125


How it works

Table makes a list of y x's. Times takes the product of all of them.`


Another way to achieve the same end:

#~Product~{i,1,#2}&

Example

#~Product~{i, 1, #2} & @@ {5, 3}

125


1

Windows Batch

Like most of the other answers here, it uses recursion.

@echo off
set y=%2
:p
if %y%==1 (
set z=%1
goto :eof
) else (
    set/a"y-=1"
    call :p %1
    set/a"z*=%1"
    goto :eof
)

x^y is stored in the environment variable z.


1

perl

Here's a tail recursive perl entry. Usage is echo $X,$Y | foo.pl:

($x,$y) = split/,/, <>;
sub a{$_*=$x;--$y?a():$_}
$_=1;
print a

Or for a more functional-type approach, how about:

($x,$y) = split/,/, <>;
$t=1; map { $t *= $x } (1..$y);
print $t

"a: stuff goto a if something" looks like a loop.
Glenn Randers-Pehrson

Yep, the goto version is a loop, but isn't tail recursion also essentially a loop?
skibrianski

1

Python

def getRootOfY(x,y):
   return x**y 

def printAnswer():
   print "answer is ",getRootOfY(5,3)
printAnswer()

answer =125

I am not sure if this is against the requirements, but if not here is my attempt.


Welcome to PPCG! When you do your language header you can leave out the "language=" since by custom everyone puts the language in the header so that's understood. You may indeed have run afoul of the rules here, but we'll let the voters decide. Glad to have a new member at the country club.
Jonathan Van Matre
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.