Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- %%%-------------------------------------------------------------------
- %%% File : bfize.erl
- %%% Author : Jesper Louis Andersen <jesper.louis.andersen@gmail.com>
- %%% Description : Brainfuckize a text message
- %%%
- %%% Created : 27 Oct 2010 by Jesper Louis Andersen <jesper.louis.andersen@gmail.com>
- %%%-------------------------------------------------------------------
- -module(bfize).
- %% API, the single export from the module, taking one parameter
- -export([bfize/1]).
- %%====================================================================
- %% API
- %%====================================================================
- bfize(FN) ->
- %% Read in the file, assume it goes well. We now have the file as a binary in memory
- {ok, Content} = file:read_file(FN),
- %% Set up an IOlist containing the initialization vector and call process with 4 counters,
- %% initialized by the IV at 70, 100, 30, and 10. We use multiple counters so we can choose the
- %% counter closest to the value we wish to output and thus get a somewhat smaller brainfuck
- %% program.
- %%
- %% IOlists are
- %% datatype iolist = L of iolist list | S of string | B of binary | C of char
- %% So we have O(1) concatenation. Many Erlang operations works on IOlists as well as they
- %% do on strings (if only ML...).
- Res = [initialization(), process(binary_to_list(Content),
- 0,
- [{1, 70}, {2, 100}, {3, 30}, {4, 10}])],
- %% Write out the resulting file.
- file:write_file(FN ++ ".bf", format(lists:flatten(Res))).
- %%====================================================================
- %% Internal functions
- %%====================================================================
- %% Simple output formatter, 40 characters per line.
- format(Lst) when length(Lst) < 40 -> Lst;
- format(Lst) ->
- {Front, Back} = lists:split(40, Lst),
- [Front, $\n, format(Back)].
- %% The initialization vector. A loop of 10 sets up 4 counters at positions 1,2,3,4
- %% on the 0-indexed tape. Values are 7*10, 10*10,3*10 and 1*10.
- initialization() ->
- "++++++++++[>+++++++>++++++++++>+++>+<<<<-]".
- %% If a counter is at Count and we want to print character Char, alter the counter so it
- %% can print the character on the next output value by adjusting it with either + or -.
- alter_counter(Char, Count) when Char == Count -> "";
- alter_counter(Char, Count) when Char > Count -> string:copies("+", Char - Count);
- alter_counter(Char, Count) when Char < Count -> string:copies("-", Count - Char).
- %% Carry out move instructions on the tape to take us from an Old Position to a new one.
- move_tape(OldPos, NewPos) when OldPos == NewPos -> "";
- move_tape(OldPos, NewPos) when OldPos > NewPos -> string:copies("<", OldPos - NewPos);
- move_tape(OldPos, NewPos) when OldPos < NewPos -> string:copies(">", NewPos - OldPos).
- %% Helper: Update a property-lists key NK with a new value NV by searching for the element
- %% to update.
- update_proplist([{K, _V} | Rest], NK, NV) when K == NK ->
- [{K, NV} | Rest];
- update_proplist([{K, V} | Rest], NK, NV) when K =/= NK ->
- [{K, V} | update_proplist(Rest, NK, NV)].
- %% Find the nearest counter to use when you want to target output of N,
- %% By searching all counters and returning the one that is closest at the
- %% moment.
- find_nearest(N, Cnt) ->
- find_nearest(N, {0, 300}, Cnt).
- find_nearest(_N, {K, V}, []) -> {K, V};
- find_nearest(N, {K, V}, [{NK, NV} | R]) ->
- case abs(N - V) < abs(N - NV) of
- true ->
- find_nearest(N, {K, V}, R);
- false ->
- find_nearest(N, {NK, NV}, R)
- end.
- %% Finally, the meat. We want to output character N.
- process([], _Pos, _Counters) -> [];
- process([N | R], Pos, Counters) ->
- %% Find the nearest counter to N
- {NPos, V} = find_nearest(N, Counters),
- %% Move the tape to the counter, update the counter, print out the desired character
- Res = [move_tape(Pos, NPos), alter_counter(N, V), $.],
- %% Process next character in the input, update the counters so we keep track of them.
- [Res | process(R, NPos, update_proplist(Counters, NPos, N))].
Add Comment
Please, Sign In to add comment