5
\$\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\$
5
  • \$\begingroup\$ Yes. There is a way to extract those two constants without accessing the AST. \$\endgroup\$
    – Joe Z.
    Apr 4, 2013 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, 2013 at 21:31
  • \$\begingroup\$ @KevinReid Done. \$\endgroup\$
    – Joe Z.
    Apr 4, 2013 at 23:03
  • \$\begingroup\$ I'm thinking of rewarding a bounty for an answer in binary lambda calculus... \$\endgroup\$
    – Joe Z.
    Nov 19, 2013 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, 2014 at 18:07

12 Answers 12

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\$
4
  • \$\begingroup\$ Save 4: {2,%/1$-{@*+}++}:k; or {2,0+%/-{@*+}++}:k; \$\endgroup\$ Apr 4, 2013 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\$ Apr 5, 2013 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, 2013 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\$ Apr 5, 2013 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\$
2
  • \$\begingroup\$ Your f(g, h, x) should be f(g, h)(x). \$\endgroup\$
    – Joe Z.
    Apr 4, 2013 at 19:14
  • \$\begingroup\$ Ok. I'll adjust accordingly \$\endgroup\$
    – DavidC
    Apr 4, 2013 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\$
4
  • 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, 2013 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, 2013 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\$ Apr 5, 2013 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, 2013 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\$
2
  • \$\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, 2013 at 19:14
  • \$\begingroup\$ @JoeZeng, I think that is more what you were after \$\endgroup\$
    – SeanC
    Apr 4, 2013 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\$
2
  • \$\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, 2013 at 8:07
  • \$\begingroup\$ I wasn't sure that'd be permitted. \$\endgroup\$
    – histocrat
    Apr 5, 2013 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\$
1
\$\begingroup\$

Jelly, 22 13 bytes

vØ.v@µI,Ḣż⁾×+

Try it online!

I think I understand what the question is asking for, but it really isn't clear exactly how the program is supposed to return \$a\$ and \$b\$, and it seems as though (given the tag) that this is an unobservable requirement)

11 bytes sacrificed to clumsy I/O formats.

-9 bytes thanks to Howard's method

This takes \$g\$ and \$h\$ in Jelly's most natural form for non-black-box functions, as a string representing a Jelly link. As \$g(x)=ax+b\$ (and similar for \$h\$), this is equivalent to a×b+. We also return \$k\$ in the form a×b+. If this can instead take input and output as two lists [a, b] representing \$g\$ and \$h\$, we can reduce this to 8 bytes.

How it works

vØ.v@µI,Ḣż⁾×+ - Main link. Takes h ("c×d+") on the left and g ("a×b+") on the right
 Ø.           - [0, 1]
v             - Run h over each; [h(0), h(1)]
   v@         - Run g over each; [g(h(0)), g(h(1))]
     µ        - New link. Call this pair l and use it as the argument
      I       - Differences; g(h(0)) - g(h(1))
        Ḣ     - Head; g(h(0))
       ,      - Pair; [g(h(0)) - g(h(1)), g(h(0))]
          ⁾×+ - Yield "×+"
         ż    - Zip together; [g(h(0)) - g(h(1)), "×", g(h(0)), "+"]
                Implicitly smash together and print
\$\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\$
1
  • \$\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\$ Apr 5, 2013 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 and acknowledge you have read our privacy policy.

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