6
\$\begingroup\$

You are given two functions g(x) and h(x), each of which takes an integer x and returns the number ax + b (where a and b are integers defined in the function).

Your task is to write a function f(g, h) that takes these two functions, and returns a function k(x) = g(h(x)), but where the procedure of k(x) is also simply of the form ax + b.

For example, given g(x) = 2x + 3 and h(x) = 3x + 4, you would need to return k(x) = 6x + 11, and not k(x) = 2(3x + 4) + 3.

\$\endgroup\$
  • \$\begingroup\$ Yes. There is a way to extract those two constants without accessing the AST. \$\endgroup\$ – Joe Z. Apr 4 '13 at 18:04
  • \$\begingroup\$ May I suggest clarifying that the return value is of function type as well, as I'm guessing is your intent? Two of the current answers return strings. \$\endgroup\$ – Kevin Reid Apr 4 '13 at 21:31
  • \$\begingroup\$ @KevinReid Done. \$\endgroup\$ – Joe Z. Apr 4 '13 at 23:03
  • \$\begingroup\$ I'm thinking of rewarding a bounty for an answer in binary lambda calculus... \$\endgroup\$ – Joe Z. Nov 19 '13 at 22:08
  • 1
    \$\begingroup\$ I don't understand how you want the output. If it's as a function, you could just black-box compose the inputs. Do you want the pair (a,b) for which k(x)=ax+b? A function that must be written in the form k(x)=ax+b? If the second, do a and b have to be given explicit assignments in that function? \$\endgroup\$ – xnor May 22 '14 at 18:07

11 Answers 11

3
\$\begingroup\$

GolfScript, 41 40 23 19 characters

{2,0+%/-{@*+}++}:k;

Thanks to Peter Taylor for pointing out this solution. Accepts two function bodies as arguments.

The following examples show how to use function k:

# As function
{2*3+} {3*4+} k         # => {11 6 @*+}

# Apply to value
5 {2*3+} {3*4+} k ~     # => 41

If one wants to retain the original output format, the following 22 character solution is possible:

{2,0+%/-{*}+\+{+}+}:k;

{2*3+} {3*4+} k         # => {6 * 11 +}

Explanation of the code:

{                       # on stack are functions g h
  2,                    # build array [0 1] -> g h [0 1]
  0+                    # append 0 -> g h [0 1 0]
  %                     # apply function h to each element -> g [h(0) h(1) h(0)]
  /                     # apply function g to each element
                        # and break up the array -> g(h(0)) g(h(1)) g(h(0))
  -                     # subtract last two -> g(h(0)) g(h(1))-g(h(0))
  {@*+}++               # append function body to these values
}:k;                    # save function to variable k
\$\endgroup\$
  • \$\begingroup\$ Save 4: {2,%/1$-{@*+}++}:k; or {2,0+%/-{@*+}++}:k; \$\endgroup\$ – Peter Taylor Apr 4 '13 at 23:07
  • \$\begingroup\$ Your explanation makes me never want to learn Golfscript. It would make my head explode trying to figure it out. \$\endgroup\$ – jdstankosky Apr 5 '13 at 12:57
  • \$\begingroup\$ @jdstankosky Do you mean the explanation is not clear (in which case I'd be happy to amend if you could point out what is unclear) or that GolfScript is - well - special (in which case you'll miss a lot of fun). \$\endgroup\$ – Howard Apr 5 '13 at 14:22
  • \$\begingroup\$ @Howard It's definitely interesting, incredibly confusing, and far more advanced than anything I think I'll ever be able to figure out. \$\endgroup\$ – jdstankosky Apr 5 '13 at 14:26
2
\$\begingroup\$

Mathematica 15

Define g, h as pure functions

g and h are defined as pure functions (awaiting a value or independent variable to be assigned)

g = 2 # + 3 &;
h = 3 # + 4 &;
g[x]
h[x]

3 + 2 x
4 + 3 x


Method #1: Compose g of h directly (15 chars)

g@h@x//Simplify

11 + 6 x

Or, alternatively: (17 chars)

g[h[x]]//Simplify

Method #2: Define f (25 chars= 13 + 10 chars for Simplify)

f=Composition

composition

f[g, h][x]
f[g, h][x] // Simplify
Composition[g, h][x]//Simplify
f[g, h][1]
Table[f[g, h][x], {x, 1, 13}]

3 + 2 (4 + 3 x)
11 + 6 x
11 + 6 x
17
{17, 23, 29, 35, 41, 47, 53, 59, 65, 71, 77, 83, 89}

\$\endgroup\$
  • \$\begingroup\$ Your f(g, h, x) should be f(g, h)(x). \$\endgroup\$ – Joe Z. Apr 4 '13 at 19:14
  • \$\begingroup\$ Ok. I'll adjust accordingly \$\endgroup\$ – DavidC Apr 4 '13 at 19:14
2
\$\begingroup\$

Haskell, 31

(f%g)x=f(g 0)+x*(f(g 1)-f(g 0))

Version in which the function body contains only variables (equivalent at run time, but closer to the question's form), 38 characters:

(f%g)x=a*x+b where h=f.g;b=h 0;a=h 1-b

Note that in both cases, since Haskell uses curried functions, there is no explicit construction of the composed function as it is implicit in % being defined with three arguments: function f, function g, value x.

Example use:

> ((\x -> 2*x + 3)%(\x -> 3*x + 4)) 0
11
> ((\x -> 2*x + 3)%(\x -> 3*x + 4)) 4
35

Ungolfed second form:

(f % g) x = a * x + b        -- equivalent: (f % g) = \x -> a * x + b
  where
    h = f . g                -- use built in function composition to bootstrap
    b = h 0                  -- constant term of composed function
    a = h 1 - h 0            -- linear term of composed function
\$\endgroup\$
  • 1
    \$\begingroup\$ This can be shortened to f%g=f(g 0)!(f(g 1-g 0)-f 0);(z!y)x=y*x+z (40 chars) by replacing the where clause with a function call (which also gets rid of the lambda) and defining infix operators instead of plain functions. Also, I'm not sure if it's necessary to share the values of y and z, so you may be able to improve it further by inlining them as well. \$\endgroup\$ – hammar Apr 4 '13 at 23:51
  • \$\begingroup\$ @hammar I have my doubts that putting the expressions inline is in the spirit of the question (“the procedure of k(x) is also simply of the form ax + b”) but OK, I'll take the edit, unless Joe Zeng disagrees. \$\endgroup\$ – Kevin Reid Apr 5 '13 at 18:02
  • \$\begingroup\$ Either way, f(g 1)-f(g 0) is one char shorter than f(g 1-g 0)-f 0. \$\endgroup\$ – Peter Taylor Apr 5 '13 at 20:36
  • \$\begingroup\$ @PeterTaylor Good point! In fact, that made me realize I was missing a trick in the original version: I now define h = f . g and derive all results from h, saving another two characters — I was previously stuck on the notion of extracting the coefficients of each function individually. \$\endgroup\$ – Kevin Reid Apr 5 '13 at 22:22
1
\$\begingroup\$

Lua, 87

function f(g, h)local a,b=g(h(1))-g(h(0)),g(h(0))return function(x)return a*x+b end end
\$\endgroup\$
1
\$\begingroup\$

vba, 89

Function f(g,h,x)
f=Evaluate(Replace(g,"x","*("&Replace(h,"x","*"&x)&")"))  
End Function

usage/result

?f("2x+3","3x+4",1)
17

\$\endgroup\$
  • \$\begingroup\$ The functions aren't supposed to be strings. Can you evaluate the string directly with a number and get the result of the function out? \$\endgroup\$ – Joe Z. Apr 4 '13 at 19:14
  • \$\begingroup\$ @JoeZeng, I think that is more what you were after \$\endgroup\$ – SeanC Apr 4 '13 at 19:55
1
\$\begingroup\$

Ruby >=1.9, 55

f=->g,h{a=(g[1]-g[0])*(h[1]-h[0]);b=g[h[0]];->x{a*x+b}}

Less golfed:

def c(f,g)
  f_a=f[1]-f[0]
  g_a=g[1]-g[0]
  a=f_a*g_a
  b=f[g[0]]
  ->x{a*x+b}
end
\$\endgroup\$
  • \$\begingroup\$ You can shorten even further by inlining a: f=->g,h{->x{(g[h[1]]-b=g[h[0]])*x+b}} \$\endgroup\$ – Howard Apr 5 '13 at 8:07
  • \$\begingroup\$ I wasn't sure that'd be permitted. \$\endgroup\$ – histocrat Apr 5 '13 at 15:00
1
\$\begingroup\$

SML (60 chars)

fun f g h=let val c=g(h 0)val m=g(h 1)-c in fn x=>m*x+c end;

Ungolfed:

fun f g h =
    let val c = g (h 0)
        val m = g (h 1) - c
     in fn x => m*x + c
    end;
\$\endgroup\$
0
\$\begingroup\$

PHP 72

Apparently I completely missed the point of this code-golf. I'm STILL not sure if I understand it correctly. Is no output required? Can I assume the methods of g and h? Here's a new version based off the old one:

<?=$f=function($g,$h,$x){return$k=($g[0]*$h[0]*$x)+($g[0]*$h[1])+$g[1];}

If this is still wrong, I give up.


PHP 176

The requirements are kind of confusing, but here's what I think you meant:

<?=f($argv);function f($a){$x=$a[3];$g=explode("x",$a[1]);$h=explode("x",$a[2]);return$k=($g[0]*$h[0])."*$x+".(($g[0]*$h[1])+$g[1])."=".(($g[0]*$h[0]*$x)+($g[0]*$h[1])+$g[1]);}

Usage: php f.php 2x+3 3x+4 5

Output: 6*5+11=41

Another Example

Usage: php f.php 4x-7 3x+4 2

Output: 12*2+9=33

Method

As you described, we can't simply output the answer with g(h(x)), we had to create function f(g,h) which determines what both the functions would be together, and return that as a new function: k(x).

Is this what OP meant?

Ungolfed

<?php

function f($a) {
    $x=$a[3];
    $g=explode("x",$a[1]);
    $h=explode("x",$a[2]);
    $k  = $g[0]*$h[0];
    $k .= "*";
    $k .= $x;
    $k .= "+";
    $k .= ($g[0]*$h[1])+$g[1];
    $k .= " = ";
    $k .= ($g[0]*$h[0]*$x) + ($g[0]*$h[1])+$g[1];
    return $k;
}

echo f($argv);
\$\endgroup\$
  • \$\begingroup\$ In PHP terminology, the requirements are asking for a function which takes two callbacks as arguments and returns a callback. As an implementation note, I would expect to see a couple of calls to call_user_func and probably a call to create_function. \$\endgroup\$ – Peter Taylor Apr 5 '13 at 8:50
0
\$\begingroup\$

Erlang 54:

1> F = fun(G,H)->B=G(H(0)),A=G(H(1))-B,fun(X)->A*X+B end end.
2> (F(fun(X) -> 2*X+3 end, fun(X) -> 3*X + 4 end))(0).
11
3> (F(fun(X) -> 2*X+3 end, fun(X) -> 3*X + 4 end))(1) - v(2).
6
\$\endgroup\$
0
\$\begingroup\$

Common Lisp (108)

(defun f(g h)(let*((d(g 0))(c(-(g 1)d))(z(h 0))(e(-(h 1)z))(a(* c e))(b(+(* c z)d)))(lambda(x)(+(* a x)b))))

It could be shorter if I assumed expressions would have constants folded...but I didn't make that assumption to make sure I met the spec. Also, I have implemented Clojure's literal anonymous function syntax as a read macro. I decided against using that as well.

\$\endgroup\$
0
\$\begingroup\$

Postscript, 120

/f{1 index 0 get dup 
2 index 0 get mul exch
3 2 roll 2 get mul 
3 2 roll 2 get add[3 1 roll/mul cvx exch/add cvx]cvx}def

Ungolfed and commented with testing.

/g{2 mul 3 add}def
/h{3 mul 4 add}def

/f{
    1 index 0 get % g h g[0]
    dup 2 index 0 get mul % g h g[0] g[0]*h[0]
    exch 3 2 roll 2 get mul % g g[0]*h[0] g[0]*h[2]
    3 2 roll 2 get add % g[0]*h[0] g[0]*h[2]+g[2]
    [ 3 1 roll /mul cvx exch /add cvx ] cvx 
}def

//g //h f ==

Output:

GPL Ghostscript 9.10 (2013-08-30)
Copyright (C) 2013 Artifex Software, Inc.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
{6 mul 11 add}
GS>
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.