This is a partial solution and probably it's not what you want. However, I'm posting it solely for record purposes, in case anyone would need it. =)
I'll use Maxima:
Maxima is a system for the manipulation of symbolic and numerical expressions, including differentiation, integration, Taylor series, Laplace transforms, ordinary differential equations, systems of linear equations, polynomials, and sets, lists, vectors, matrices, and tensors. Maxima yields high precision numeric results by using exact fractions, arbitrary precision integers, and variable precision floating point numbers. Maxima can plot functions and data in two and three dimensions.
First of all, I created a script file named solve.cmd in my working directory:
@echo off
rem If Maxima is not in your path, you need to set it.
rem Also, I'm making use of the 'head' command, you can
rem obtain the Win32 version easily with MSys.
set PATH=%PATH%;"C:\Program Files\Maxima-5.24.0\bin"
maxima --very-quiet -r %1 | head --lines=-1
I'm not in my Linux box right now, but a .sh file is similar.
Using Jake's code, I added a call to this script:
\documentclass{article}
\usepackage{pgf}
\begin{document}
\section{Problem}
\pgfmathsetseed{1}
\pgfmathtruncatemacro\coeffa{random(2,10)}
\pgfmathtruncatemacro\coeffb{random(2,10)}
\pgfmathtruncatemacro\coeffc{random(2,10)}
% call to the 'solve' script providing the coefficients.
% Maxima's 'solve' function will return x1 and x2, and the
% 'tex' function will convert the answer to TeX. The last
% line of the output will be removed (the 'head' command)
% because Maxima adds a 'false' line to the end of the file.
% Then we redirect the output to a file.
\immediate\write18{solve.cmd "tex(solve(\coeffa*x^2 + (\coeffb*x) + (\coeffc)));" > solution1.tex}
Let \(x_1\) and \(x_2\) be the roots of \(\coeffa x^2 +\coeffb x +\coeffc=0\). Find \(x_1x_2\).
\section{Solution}
% read the solution
\input solution1
\end{document}
I tried to use Maxima's plot2d
function together with the call, but I failed to fix a minor error with file extensions. I intended to create a png
plot with gnuplot
and include it. Sorry, it didn't work yet.
Don't forget to use the --shell-escape
or --enable-write18
flag.
EDIT: It gave me a tremendous headache, but I guess I found a nice improvement. =)
I'm not used to Maxima, though I like to use it for simple calculations. If my code is somehow incorrect, please help me improve it. Thanks.
I edited the solve.cmd file in my working directory to look like this:
@echo off
rem If Maxima is not in your path, you need to set it.
rem Now, I don't use 'head' anymore, but 'grep'. The idea
rem behind this code is:
rem 1. generate the three coefficients,
rem 2. output both equation and solution to a file,
rem 3. get rid of the 'false' lines in the text (Maxima's fault)
rem (we do this thanks to 'grep' using an inverse flag)
rem 4. direct output to a file 'problem.txt'.
@echo off
set PATH=%PATH%;"C:\Program Files\Maxima-5.24.0\bin"
maxima --very-quiet -r "s: make_random_state(true)$ set_random_state(s)$ fullrand(low, high) := floor(random(1.0) * ( 1 + high - low)) + low$ a : fullrand(-10,10)$ s: b : fullrand(-10,10)$ c : fullrand(-10,10)$ tex(a*x^2 + b*x + c); tex(solve(a*x^2 + b*x + c));" | grep -v false > problem.txt
Now the tricky part, the LaTeX code:
\documentclass{article}
\immediate\write18{solve.cmd}
\newread\myread
\openin\myread=problem.txt
\read\myread to \theequation
\read\myread to \thesolution
\begin{document}
\section{Problem}
This is our equation:
\theequation
\section{Solution}
And this is our solution:
\thesolution
\end{document}
Let's check the code: first of all, we run solve.cmd
, which outputs both equation and solution to a file named problem.txt
. Then we create a \newread\myread
and open this file \openin\myread=problem.txt
. Now we map the first line to \theequation
(which is the equation which we defined in our Maxima code) and the second line to \thesolution
(same logic). Then we call it when needed.
Again, probably some of my Maxima code is faulty. But I hope you get the idea behind this. In case of changing the equation or solution to a inline version, we may probably do some sed
in it and replace the pattern. =)
Just to get the ball rolling (and to get to play with MetaPost), here is what I have so far:
(updated with a few ideas I had, I still need to test out Barbara’s and mforbes’ hints and ideas)
beginfig(1);
defaultscale := .8; % make the text a little smaller
u := 1.5in;
phi := 1.618033988749895;
for i:= 0 upto 5: z.hexc[i] = right scaled u rotated (i*360/6); endfor;
path hexa; hexa := for i:=0 upto5: z.hexc[i]--endfor cycle;
fill hexa withcolor .9[green,white]; draw hexa;
dotlabel.rt("r", z.hexc0); dotlabel.urt("ur", z.hexc1);
dotlabel.ulft("ul", z.hexc2); dotlabel.lft("l", z.hexc3);
dotlabel.llft("ll", z.hexc4); dotlabel.lrt("lr", z.hexc5);
path recto; recto := z.hexc1--z.hexc2--z.hexc4--z.hexc5--cycle;
path verso; verso := recto shifted (-1u,0);
for i:=verso,recto:%,recto shifted (1u,0):
draw i withpen pencircle scaled 1.2; endfor;
picture mforbes; mforbes :=
image(
z.a = (1.27106916798686u, 0.469505571318668u);
z.tll = (0.117300021398114u, 0.294835256924744u);
z.tlr = (0.798192881206518u, 0.294835256924744u);
z.tur = (0.798192881206518u, 1.61553741320908u);
z.tul = (0.117300021398114u, 1.61553741320908u);
z.x = (0.435936138301u, 0);
z.y = (0.689095323638u, 1.73205080756888u);
dotlabels.lrt(a,tll,tlr,tur,tul,x,y);
);
drawoptions( withcolor .5 red );
draw mforbes shifted llcorner recto;
% Bringhurst's lines:
draw z.hexc1--z.hexc3--z.x shifted llcorner recto--z.hexc0--
z.y shifted llcorner recto--z.hexc4--z.a shifted llcorner recto--z.hexc2
%dashed evenly
;
drawoptions();
% Van de Graaf: http://en.wikipedia.org/wiki/Canons_of_page_construction
picture van_de_Graaf; van_de_Graaf := image(
path Van_de_Graaf[];
Van_de_Graaf0 := ulcorner verso--lrcorner recto--ulcorner recto
--llcorner verso--urcorner recto;
draw Van_de_Graaf0 dashed evenly;
% subpath (0,1) is the first line, (1,2) is the second, etc.
z.vdG0 = (subpath(3,4) of Van_de_Graaf0) intersectiontimes
(subpath(3,4) of hexa);
z.vdG1 = point xpart z.vdG0 of subpath(3,4) of hexa; % show this point
z.vdG2 = point ypart z.vdG0 of subpath(1,2) of hexa; % on this path
% ypart(z.vdG1) == xpart(z.vdG1) ?
dotlabel.lft("vdG1", z.vdG1);
dotlabel.urt("vdG2", z.vdG2);
% Close, but no cigar. Back to the drawing board.
% van de Graaf continued to project lines from the intersections:
z.vdG3 = (subpath(1,2) of Van_de_Graaf0) intersectionpoint
(subpath(3,4) of Van_de_Graaf0);
z.vdG4 = (xpart z.vdG3, ypart urcorner recto);
z.vdG5 = (subpath(0,1) of Van_de_Graaf0) intersectionpoint
(subpath(2,3) of Van_de_Graaf0);
z.vdG6 = (xpart z.vdG5, ypart urcorner verso);
dotlabels.ulft(vdG3, vdG4, vdG5, vdG6);
Van_de_Graaf1 := (z.vdG5)--(z.vdG4);
Van_de_Graaf2 := (z.vdG6)--(z.vdG3);
drawoptions( dashed evenly );
draw Van_de_Graaf1; draw Van_de_Graaf2;
drawoptions();
% Nope. Not even close.
z.guess_a = whatever[z.vdG6,z.vdG3] = whatever[z.hexc0,z.hexc5];
% Did I hit it? Pleasepleasepleasepleaseplease...
dotlabel.lrt("guess a", z.guess_a);
% Nope.
% That intersection of cross-page vdG's looks promising
);
draw van_de_Graaf withcolor .5 white;
z.golden1 = point 1/phi of subpath(5,4) of hexa;
z.golden2 = point 1/phi of subpath(2,1) of hexa;
drawoptions( withcolor .5[green,red] );
dotlabel.bot(btex $\phi$ etex, z.golden1);
dotlabel.top(btex $\phi$ etex, z.golden2);
drawoptions();
endfig;
end
(I haven't used MetaPost much, so if you have suggestions on improving, please share)
Best Answer
I'll never be as festive and cheerful as Tom Bombadil so I won't even try. I just want to tackle the minimal problem using only LaTeX.
The following code distributes an arbitrary number of nonintersecting rectangles (with independent sizes) inside a rectangular field. The algorithm is just brute force with a threshold limiting the maximum number of attempts to place a rectangle; if exceeded, an error is thrown.
It's quite gross, but it works relatively well as long as there are just a few windows and these are much smaller than the field. Also, it's just eighty lines.
Each run gives a different result, as long as you wait a minute: TiKz default seed for pseudorandom numbers is
\time*\year
. If you want it to change every time just compile using the unix timestamp as a seed:This also allows for reproducibility. The seed
123
has a runtime of a couple of seconds and outputsNot pretty, but I think the criteria are all satisfied.
UPDATED: aesthetics
I managed to throw some eye candy together while still keeping the code under 150 lines. Since the ordinary Christmas theme is already being adequately developed, I considered the alternative viewpoint.
Here is the code:
Here is the output with
seed=24122015
:What's this? What's this? There's color everywhere! What's this? There's white things in the air! What's this? I can't believe my eyes, I must be dreaming; wake up, Jack, this isn't fair! What's this?
I admit the picture suffers from a distinct lack of spiders, snakes and shrunken heads. Maybe next year I'll get around to drawing some delightful surprises to hide behind the windows.