Write a function that reduces compositions of linear operators

6

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.

Joe Z.

Posted 2013-04-04T17:59:16.907

Reputation: 30 589

Yes. There is a way to extract those two constants without accessing the AST. – Joe Z. – 2013-04-04T18:04:03.837

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. – Kevin Reid – 2013-04-04T21:31:09.017

@KevinReid Done. – Joe Z. – 2013-04-04T23:03:54.877

I'm thinking of rewarding a bounty for an answer in binary lambda calculus... – Joe Z. – 2013-11-19T22:08:26.840

1I 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? – xnor – 2014-05-22T18:07:16.983

Answers

3

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

Howard

Posted 2013-04-04T17:59:16.907

Reputation: 23 109

Save 4: {2,%/1$-{@*+}++}:k; or {2,0+%/-{@*+}++}:k; – Peter Taylor – 2013-04-04T23:07:53.073

Your explanation makes me never want to learn Golfscript. It would make my head explode trying to figure it out. – jdstankosky – 2013-04-05T12:57:16.073

@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). – Howard – 2013-04-05T14:22:31.700

@Howard It's definitely interesting, incredibly confusing, and far more advanced than anything I think I'll ever be able to figure out. – jdstankosky – 2013-04-05T14:26:25.917

2

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}

DavidC

Posted 2013-04-04T17:59:16.907

Reputation: 24 524

Your f(g, h, x) should be f(g, h)(x). – Joe Z. – 2013-04-04T19:14:09.293

Ok. I'll adjust accordingly – DavidC – 2013-04-04T19:14:40.827

2

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

Kevin Reid

Posted 2013-04-04T17:59:16.907

Reputation: 1 693

1This 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. – hammar – 2013-04-04T23:51:57.273

@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. – Kevin Reid – 2013-04-05T18:02:12.853

Either way, f(g 1)-f(g 0) is one char shorter than f(g 1-g 0)-f 0. – Peter Taylor – 2013-04-05T20:36:20.630

@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. – Kevin Reid – 2013-04-05T22:22:04.887

1

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

SeanC

Posted 2013-04-04T17:59:16.907

Reputation: 1 117

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? – Joe Z. – 2013-04-04T19:14:42.937

@JoeZeng, I think that is more what you were after – SeanC – 2013-04-04T19:55:53.987

1

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

Egor Skriptunoff

Posted 2013-04-04T17:59:16.907

Reputation: 688

1

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

histocrat

Posted 2013-04-04T17:59:16.907

Reputation: 20 600

You can shorten even further by inlining a: f=->g,h{->x{(g[h[1]]-b=g[h[0]])*x+b}} – Howard – 2013-04-05T08:07:36.457

I wasn't sure that'd be permitted. – histocrat – 2013-04-05T15:00:54.180

1

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;

Peter Taylor

Posted 2013-04-04T17:59:16.907

Reputation: 41 901

0

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);

jdstankosky

Posted 2013-04-04T17:59:16.907

Reputation: 1 474

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. – Peter Taylor – 2013-04-05T08:50:01.173

0

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

Hynek -Pichi- Vychodil

Posted 2013-04-04T17:59:16.907

Reputation: 350

0

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.

protist

Posted 2013-04-04T17:59:16.907

Reputation: 570

0

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>

luser droog

Posted 2013-04-04T17:59:16.907

Reputation: 4 535