previndexinfo

code guessing, round #106, stage 2 (guessing)

started at ; stage 2 since . guess by

specification

hello! welcome to episode 2 of "making a text editor, even though we made one before". today's challenge is to justify a text. submissions may be written in any language.

justification is the process of stretching or compressing the spaces between words and between glyphs or letters in order to align both the left and right ends of consecutive lines of text. you may be familiar with it if you've used office programs like LibreOffice, ONLYOFFICE or OpenOffice before.

this challenge implicitly requires you to wrap the text as well, both because IFcoltransG suggested it can be a continuation of the previous text editor task and because you can only justify one line of text for so long. but beware: this is not word wrapping; breaking words up is completely legal and sometimes even required. you can replace space characters with newlines, hyphenate a word or invent creative ways of wrapping your own.

the input may contain multiple paragraphs, which should be wrapped and justified independently. you are free to decide what constitutes a paragraph.

also, the message I got from IFcoltransG mentioned the number 72 several times, so I guess my brand-new code guessing editor v2 is 72 columns wide.

your challenge, given an ASCII string with space characters in it, is to justify (and wrap) the paragraphs in it using the rules above. as any language is allowed, there is no fixed API.

players

  1. Dolphy
  2. evie
  3. Indigo
  4. kimapr
  5. olive
  6. rbca
  7. undefined

entries

you can download all the entries

entry #1

comments 0

post a comment


cappuccina.bal ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// Ballerina Cappuccina is here to justify your text!

import   ballerina/io;   type  stringOrInt  string|int;  any  bigword  =
`Here_is_an_example_of_a_word_so_long_it_will_have_to_be_BROKEN_by_the_-
word_wrapping_algorithm._It_goes_on_for_150_characters_before_it_finall-
y_ends`;

public    function    main()     {     string    data    =    checkpanic
io:fileReadString("/dev/stdin"); stringOrInt[][] lines = [];  int maxlen
= 72;

{ int i = 0; stringOrInt[]  line  = []; int nlength = 0; string[] word =
[]; function() pushw = function() { if word.length()  > 0 { string sword
= string:'join("", ...word); int wlen = (line.length() > 0  ?  1  : 0) +
sword.length();  if  nlength  + wlen > maxlen { lines.push(line); line =
[];  nlength  =  0;   }   if   line.length()   >  0  {  line.push(1);  }
line.push(sword); nlength = nlength + wlen; word =  [];  } }; while true
{ if i >= data.length() { pushw(); break; } int  ii  =  i;  string  c  =
data[i];  i  = i + 1; if c == "\u{20}" || c == "\u{9}" || c  ==  "\n"  {
pushw();  } else  {  if  word.length()  ==  maxlen  {  string  borrow  =
word.pop(); word.push("-");  pushw(); word.push(borrow); } word.push(c);
continue; } if  ii+2  <  data.length() && c == "\u{20}" && data[ii+1] ==
"\u{20}" && data[ii+2] == "\n" {  lines.push(line); line = []; nlength =
0; i = i + 2; continue;  }  if  (ii+1  <  data.length()  && c == "\n" &&
data[ii+1]   ==   "\n")   ||  (c  ==  "\n"  &&  line.length()  ==  0)  {
lines.push(line);  line  =  [];   nlength   =   0;   continue;  }  }  if
line.length() > 0 { lines.push(line); line = []; nlength = 0; } }

{ int li = 0; int wi =  0;  while  true  {  if  li+1 >= lines.length() {
break;  }  int  ili  =  li;  var  line  =  lines[li];  li = li +  1;  if
line.length()  <=  1  ||  lines[ili+1].length()  ==  0 { continue; } int
length = 0; foreach string|int o in  line  {  if  o  is  int  { length =
length  + o; } else { length = length + o.length(); } } while  length  <
maxlen {  wi  = (wi + 1) % line.length(); stringOrInt spc = line[wi]; if
spc is int {  length  =  length  +  1;  line[wi]  =  spc  +  1; } else {
continue; } } } }

foreach    any    nline    in    lines   {   io:println(string:'join("",
...nline.map(function(stringOrInt el) returns string {  if  el is string
{ return el; } else { string[]  spc  = []; foreach int _ in int:range(0,
el, 1) { spc.push("\u{20}"); } return string:'join("", ...spc); }  })));
} }

entry #2

comments 0

post a comment


input.txt ASCII text, with very long lines (1111)
1
Call me Ishmael. Some years ago- never mind how long precisely- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I have of driving off the spleen and regulating the circulation. Whenever I find myself growing grim about the mouth; whenever it is a damp, drizzly November in my soul; whenever I find myself involuntarily pausing before coffin warehouses, and bringing up the rear of every funeral I meet; and especially whenever my hypos get such an upper hand of me, that it requires a strong moral principle to prevent me from deliberately stepping into the street, and methodically knocking people's hats off- then, I account it high time to get to sea as soon as I can. This is my substitute for pistol and ball. With a philosophical flourish Cato throws himself upon his sword; I quietly take to the ship. There is nothing surprising in this. If they but knew it, almost all men in their degree, some time or other, cherish very nearly the same feelings towards the ocean with me. 
justifaction.lua ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
local I = io.read"a"
local W,H,depth,idx = I:match"P5\n(%d+) (%d+)\n(%d+)\n()"
W,H,depth = tonumber(W),tonumber(H),tonumber(depth)
local R = {} for y=1,H do R[y]={} for x=1,W do
	R[y][x]=I:sub(idx,idx):byte()  idx=idx+1 end end
local function lerp(a,b,t) return (1-t)*a + t*b end
local function scrunkle(row, from,to, len) local o={} for i=1,len do
	local x = (i-1)/(len-1) * (to-from) + from
	local j = math.floor(x)
	local p0,p1 = row[j] or 0, row[j+1] or 0
	o[i] = math.floor(lerp(p0,p1,x-j)) end return o end
local function extents(row,m,M)
	m=m or math.huge  M=M or -math.huge
	for i,px in ipairs(row) do if px~=255 then
		m=math.min(m,i) M=math.max(M,i) end end
	return m,M end
local B = {} for y=1,H do B[y]=true for x=1,W do
	B[y] = B[y] and R[y][x]==255 end end
local function blockend(y) for y1 = y,H do
	if B[y1] then return y1-1 end end return H end

local S={}
if os.getenv"WORSE" then
	for y=1,H do
		local m,M = extents(R[y])
		if M<m then S[y]=R[y] else S[y]=scrunkle(R[y],m,M,W) end end
else
	local y = 1 repeat if B[y] then S[y]=R[y] y=y+1 else
		local y0,y1 = y,blockend(y)
		local m,M = math.huge,-math.huge
		for yy=y0,y1 do m,M = extents(R[yy],m,M) end
		for yy=y0,y1 do S[yy]=scrunkle(R[yy],m,M,W) end
		y = y1+1 end
	until y>H end

io.write(("P5\n%d %d\n%d\n"):format(W,H,depth))
for y=1,H do for x=1,W do io.write(string.char(S[y][x])) end end
main.sh ASCII text
1
2
3
4
5
6
7
8
9
#!/bin/bash
if [ $# -ne 2 ]; then
	echo "usage: $0 input.txt output.png" >&2
	exit 1
fi

pango-view --dpi=120 -w 400 -qo /tmp/$$.png "$1"
pngtopnm </tmp/$$.png | ppmtopgm | lua justifaction.lua | pnmtopng >"$2"
rm /tmp/$$.png
output.png PNG image data, 687 x 452, 8-bit grayscale, non-interlaced

entry #3

comments 0

post a comment


justify.ps1 ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
using namespace System.Collections.Generic;
using namespace System.Text

[CmdletBinding()]
param(
    [Parameter(
        Position = 0,
        Mandatory = $true,
        ValueFromPipeline = $true,
        ValueFromPipelineByPropertyName = $true)]
    [string]$InputFile,

    [Parameter()]
    [int]$WrapLength = 72
)
process {
    [string[]]$lines = Get-Content -Path $InputFile
    [StringBuilder]$buffer = [StringBuilder]::new()

    foreach ($line in $lines) {
        [int]$count = 0
        [List[string]]$line_words = [List[string]]::new()

        foreach ($word in $line.Split(' ')) {
            if ($count + $word.Length + $line_words.Count -gt $WrapLength) {
                [int]$padding = $WrapLength - $count
                [double]$space = $padding / ($line_words.Count - 1)
                
                [double]$cursor = 0
                [double]$ideal = 0

                foreach ($word in $line_words) {
                    while ($cursor -lt [Math]::Round($ideal)) {
                        [void]$buffer.Append(' ')
                        $cursor += 1
                    }

                    [void]$buffer.Append($word)
                    $cursor += $word.Length
                    $ideal += $word.Length + $space
                }

                [void]$buffer.Append("`n")
                $count = 0
                $line_words.Clear()
            }
            else {
                $count += $word.Length
                $line_words.Add($word)
            }
        }
        [void]$buffer.AppendJoin(' ', $line_words)
        [void]$buffer.Append("`n")
    }

    Write-Output $buffer.ToString()
}

entry #4

comments 0

post a comment


dir entry
dir src
main.rs ASCII text
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
use regex::{Regex, RegexBuilder};

fn wrap_and_justify(para: &str, width: usize) -> String {
    let lines = wrap(para, width);
    justify(lines, width)
}

fn wrap(para: &str, width: usize) -> Vec<String> {
    let mut lines: Vec<String> = Vec::new();
    let chars: Vec<char> = para.chars().collect();

    let mut i: usize = 0;
    let mut line: Vec<char> = Vec::new();
    let mut in_space: bool = false;
    while i < chars.len() {
        let ch = chars[i];
        if line.is_empty() && ch.is_whitespace() {
            i += 1;
            continue;
        }
        if line.len() != width - 1 {
            if ch == ' ' {
                if !in_space {
                    line.push(ch);
                    in_space = true;
                }
            }
            else if ch == '\n' {
                in_space = false;
                lines.push(String::from_iter(line.clone()));
                line.clear();
            }
            else {
                in_space = false;
                line.push(ch);
            }
            i += 1;
            continue;
        }
        if ch.is_alphabetic() {
            let next_ws = chars.get(i + 1).is_none_or(|c| c.is_whitespace());
            let prev_ws = i.checked_sub(1).is_none_or(|p| chars[p].is_whitespace());
            if next_ws {
                line.push(ch);
                i += 1;
            } else if !prev_ws {
                line.push('-');
            }
        } else {
            line.push(ch);
            i += 1;
        }
        lines.push(String::from_iter(line.clone()));
        line.clear();
    }
    if !line.is_empty() {
        lines.push(String::from_iter(line));
    }
    lines
}

fn justify(lines: Vec<String>, width: usize) -> String {
    let mut justified_lines: Vec<String> = Vec::new();
    let word_pattern: Regex = Regex::new(r"\S+").unwrap();

    for l in lines {
        let mut effective_len = 0;
        let mut words: Vec<&str> = Vec::new();
        word_pattern.find_iter(l.as_str()).for_each(|e|{
            let s = e.as_str();
            effective_len += s.len();
            words.push(s);
        });
        if words.is_empty() {
            justified_lines.push(String::new());
            continue;
        }

        let width_diff = width - effective_len;
        let spaces_len = words.len() - 1;
        if spaces_len == 0 {
            justified_lines.push(words[0].to_string());
            continue;
        }
        let space_each: usize = width_diff / spaces_len;
        let mut spaces: Vec<usize> = vec![space_each; spaces_len];
        let rem = width_diff % spaces_len;
        let right = spaces_len - 1;
        let increment = spaces_len.checked_div(rem).unwrap_or(1);
        space_adjust(&mut spaces, rem, 0, right, increment);

        let mut ll = String::new();
        for i in 0..words.len() {
            ll.push_str(words[i]);
            if i != spaces_len {
                ll.push_str(&" ".repeat(spaces[i]));
            }
        }
        justified_lines.push(ll);
    }

    justified_lines.join("\n")
}

fn space_adjust(spaces: &mut Vec<usize>, rem: usize, left: usize, right: usize, inc: usize) {
    if rem == 0 {
        return;
    }
    if rem == 1 {
        let idx = (right + left) / 2;
        spaces[idx] += 1;
        return;
    }
    spaces[left] += 1;
    spaces[right] += 1;
    space_adjust(spaces, rem - 2, left + inc, right - inc, inc);
}

fn entry(text: &str, width: usize) -> String {
    let paragraph_pattern: Regex = RegexBuilder::new(r"(?:.(?:.*\n?))+\n?")
                                    .unicode(true)
                                    .build()
                                    .unwrap();

    let paragraphs = paragraph_pattern.captures_iter(text);
    let mut result: Vec<String> = Vec::new();
    paragraphs.for_each(|e| {
        result.push(
            wrap_and_justify(
                e.get(0).unwrap().as_str().trim_end_matches('\n'),
                width
            )
        );
    });
    result.join("\n\n")
}
Cargo.toml ASCII text
1
2
3
4
5
6
7
[package]
name = "cg106"
version = "0.1.0"
edition = "2024"

[dependencies]
regex = "1.13.1"

entry #5

comments 0

post a comment


futural.jhf ASCII text
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
12345  1JZ
12345  9MWRFRT RRYQZR[SZRY
12345  6JZNFNM RVFVM
12345 12H]SBLb RYBRb RLOZO RKUYU
12345 27H\PBP_ RTBT_ RYIWGTFPFMGKIKKLMMNOOUQWRXSYUYXWZT[P[MZKX
12345 32F^[FI[ RNFPHPJOLMMKMIKIIJGLFNFPGSHVHYG[F RWTUUTWTYV[X[ZZ[X[VYTWT
12345 35E_\O\N[MZMYNXPVUTXRZP[L[JZIYHWHUISJRQNRMSKSIRGPFNGMIMKNNPQUXWZY[[[\Z\Y
12345  8MWRHQGRFSGSIRKQL
12345 11KYVBTDRGPKOPOTPYR]T`Vb
12345 11KYNBPDRGTKUPUTTYR]P`Nb
12345  9JZRLRX RMOWU RWOMU
12345  6E_RIR[ RIR[R
12345  8NVSWRXQWRVSWSYQ[
12345  3E_IR[R
12345  6NVRVQWRXSWRV
12345  3G][BIb
12345 18H\QFNGLJKOKRLWNZQ[S[VZXWYRYOXJVGSFQF
12345  5H\NJPISFS[
12345 15H\LKLJMHNGPFTFVGWHXJXLWNUQK[Y[
12345 16H\MFXFRNUNWOXPYSYUXXVZS[P[MZLYKW
12345  7H\UFKTZT RUFU[
12345 18H\WFMFLOMNPMSMVNXPYSYUXXVZS[P[MZLYKW
12345 24H\XIWGTFRFOGMJLOLTMXOZR[S[VZXXYUYTXQVOSNRNOOMQLT
12345  6H\YFO[ RKFYF
12345 30H\PFMGLILKMMONSOVPXRYTYWXYWZT[P[MZLYKWKTLRNPQOUNWMXKXIWGTFPF
12345 24H\XMWPURRSQSNRLPKMKLLINGQFRFUGWIXMXRWWUZR[P[MZLX
12345 12NVROQPRQSPRO RRVQWRXSWRV
12345 14NVROQPRQSPRO RSWRXQWRVSWSYQ[
12345  4F^ZIJRZ[
12345  6E_IO[O RIU[U
12345  4F^JIZRJ[
12345 21I[LKLJMHNGPFTFVGWHXJXLWNVORQRT RRYQZR[SZRY
12345 56E`WNVLTKQKOLNMMPMSNUPVSVUUVS RQKOMNPNSOUPV RWKVSVUXVZV\T]Q]O\L[JYHWGTFQFNGLHJJILHOHRIUJWLYNZQ[T[WZYYZX RXKWSWUXV
12345  9I[RFJ[ RRFZ[ RMTWT
12345 24G\KFK[ RKFTFWGXHYJYLXNWOTP RKPTPWQXRYTYWXYWZT[K[
12345 19H]ZKYIWGUFQFOGMILKKNKSLVMXOZQ[U[WZYXZV
12345 16G\KFK[ RKFRFUGWIXKYNYSXVWXUZR[K[
12345 12H[LFL[ RLFYF RLPTP RL[Y[
12345  9HZLFL[ RLFYF RLPTP
12345 23H]ZKYIWGUFQFOGMILKKNKSLVMXOZQ[U[WZYXZVZS RUSZS
12345  9G]KFK[ RYFY[ RKPYP
12345  3NVRFR[
12345 11JZVFVVUYTZR[P[NZMYLVLT
12345  9G\KFK[ RYFKT RPOY[
12345  6HYLFL[ RL[X[
12345 12F^JFJ[ RJFR[ RZFR[ RZFZ[
12345  9G]KFK[ RKFY[ RYFY[
12345 22G]PFNGLIKKJNJSKVLXNZP[T[VZXXYVZSZNYKXIVGTFPF
12345 14G\KFK[ RKFTFWGXHYJYMXOWPTQKQ
12345 25G]PFNGLIKKJNJSKVLXNZP[T[VZXXYVZSZNYKXIVGTFPF RSWY]
12345 17G\KFK[ RKFTFWGXHYJYLXNWOTPKP RRPY[
12345 21H\YIWGTFPFMGKIKKLMMNOOUQWRXSYUYXWZT[P[MZKX
12345  6JZRFR[ RKFYF
12345 11G]KFKULXNZQ[S[VZXXYUYF
12345  6I[JFR[ RZFR[
12345 12F^HFM[ RRFM[ RRFW[ R\FW[
12345  6H\KFY[ RYFK[
12345  7I[JFRPR[ RZFRP
12345  9H\YFK[ RKFYF RK[Y[
12345 12KYOBOb RPBPb ROBVB RObVb
12345  3KYKFY^
12345 12KYTBTb RUBUb RNBUB RNbUb
12345  6JZRDJR RRDZR
12345  3I[Ib[b
12345  8NVSKQMQORPSORNQO
12345 18I\XMX[ RXPVNTMQMONMPLSLUMXOZQ[T[VZXX
12345 18H[LFL[ RLPNNPMSMUNWPXSXUWXUZS[P[NZLX
12345 15I[XPVNTMQMONMPLSLUMXOZQ[T[VZXX
12345 18I\XFX[ RXPVNTMQMONMPLSLUMXOZQ[T[VZXX
12345 18I[LSXSXQWOVNTMQMONMPLSLUMXOZQ[T[VZXX
12345  9MYWFUFSGRJR[ ROMVM
12345 23I\XMX]W`VaTbQbOa RXPVNTMQMONMPLSLUMXOZQ[T[VZXX
12345 11I\MFM[ RMQPNRMUMWNXQX[
12345  9NVQFRGSFREQF RRMR[
12345 12MWRFSGTFSERF RSMS^RaPbNb
12345  9IZMFM[ RWMMW RQSX[
12345  3NVRFR[
12345 19CaGMG[ RGQJNLMOMQNRQR[ RRQUNWMZM\N]Q][
12345 11I\MMM[ RMQPNRMUMWNXQX[
12345 18I\QMONMPLSLUMXOZQ[T[VZXXYUYSXPVNTMQM
12345 18H[LMLb RLPNNPMSMUNWPXSXUWXUZS[P[NZLX
12345 18I\XMXb RXPVNTMQMONMPLSLUMXOZQ[T[VZXX
12345  9KXOMO[ ROSPPRNTMWM
12345 18J[XPWNTMQMNNMPNRPSUTWUXWXXWZT[Q[NZMX
12345  9MYRFRWSZU[W[ ROMVM
12345 11I\MMMWNZP[S[UZXW RXMX[
12345  6JZLMR[ RXMR[
12345 12G]JMN[ RRMN[ RRMV[ RZMV[
12345  6J[MMX[ RXMM[
12345 10JZLMR[ RXMR[P_NaLbKb
12345  9J[XMM[ RMMXM RM[X[
12345 40KYTBRCQDPFPHQJRKSMSOQQ RRCQEQGRISJTLTNSPORSTTVTXSZR[Q]Q_Ra RQSSUSWRYQZP\P^Q`RaTb
12345  3NVRBRb
12345 40KYPBRCSDTFTHSJRKQMQOSQ RRCSESGRIQJPLPNQPURQTPVPXQZR[S]S_Ra RSSQUQWRYSZT\T^S`RaPb
12345 24F^IUISJPLONOPPTSVTXTZS[Q RISJQLPNPPQTTVUXUZT[Q[O
12345 35JZJFJ[K[KFLFL[M[MFNFN[O[OFPFP[Q[QFRFR[S[SFTFT[U[UFVFV[W[WFXFX[Y[YFZFZ[
oingle.lua ASCII text
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
local function mkblank(width, height)
	local t = {}
	for y = 1, height do
		local tt = {}; t[y] = tt
		for x = 1, width do
			tt[x] = false
		end
	end
	return t
end

local function output(t, width, height)
	io.write("P1\n" .. width .. " " .. height .. "\n")
	for _, tt in ipairs(t) do
		local nr = {}
		for j, v in ipairs(tt) do
			nr[j] = (v and "1" or "0")
		end
		nr[#nr + 1] = "\n"
		io.write(table.concat(nr))
	end
end




local function linedraw_naiive(t, px, py, x, y)
	while px ~= x or py ~= y do
		if px < x then px = px + 1 end
		if px > x then px = px - 1 end
		if py < y then py = py + 1 end
		if py > y then py = py - 1 end
		t[py][px] = true
	end
end

-- https://en.wikipedia.org/wiki/Bresenham's_line_algorithm#All_cases the last one
local function linedraw_bresenham_combined(t, px, py, x, y)
	local dx = math.abs(x - px)
	local sx = (px < x) and 1 or -1
	local dy = -math.abs(y - py)
	local sy = (py < y) and 1 or -1
	local error = dx + dy

	while true do
		t[py][px] = true
		local e2 = 2 * error
		if e2 >= dy then
			if px == x then break end
			error = error + dy
			px = px + sx
		end
		if e2 <= dx then
			if py == y then break end
			error = error + dx
			py = py + sy
		end
	end
end

-- local linedraw = linedraw_naiive
local linedraw = linedraw_bresenham_combined

local byte_R = string.byte("R")
local function loadhershey(source)
	local glyphs = {}
	local i = 1
	while i < #source do
		while source:sub(i, i) == "\n" do i = i + 1 end
		local id = assert(tonumber(source:sub(i, i + 4)))
		i = i + 5
		local pointn = assert(tonumber(source:sub(i, i + 2)))
		i = i + 3
		pointin, i = pointn - 1, i + 2 -- not sure what's up with this they're screwed
		local glyph = {}
		while glyphs[id] do id = id + 1 end -- maximum si
		glyphs[id] = glyph

		local part = {}
		glyph[1] = part
		for j = 1, pointn do
			local c1 = source:sub(i, i)
			if c1 == "\n" then
				i = i + 1
			elseif c1 == " " then
				part = {}
				glyph[#glyph + 1] = part
				i = i + 2
			else
				part[#part + 1] = {
					x = (c1:byte() - byte_R),
					y = (source:sub(i + 1, i + 1):byte() - byte_R),
				}
				i = i + 2
			end
		end
	end
	return glyphs
end


local space = 19
local linespace = 25
local width, height = space * 72, 600
local grid = mkblank(width, height)

--[=[
local glyphs = loadhershey([[
    1  9MWRMNV RRMVV RPSTS
    2 16MWOMOV ROMSMUNUPSQ ROQSQURUUSVOV
    3 11MXVNTMRMPNOPOSPURVTVVU
    4 12MWOMOV ROMRMTNUPUSTURVOV
    5 12MWOMOV ROMUM ROQSQ ROVUV
    6  9MVOMOV ROMUM ROQSQ
    7 15MXVNTMRMPNOPOSPURVTVVUVR RSRVR
    8  9MWOMOV RUMUV ROQUQ
    9  3PTRMRV
   10  7NUSMSTRVPVOTOS
   11  9MWOMOV RUMOS RQQUV
   12  6MVOMOV ROVUV
]])
--]=]
local glyphs
do
	-- https://solhsa.com/hershey/fontprev.html
	-- please reboop files to remove the erroneous newlines in them thanks
	local file = assert(io.open("futural.jhf", "r"))
	glyphs = loadhershey(file:read("*a"))
	file:close()
end

-- linedraw(grid, 1,1, width,height/2)

local function glyphdraw(grid, id, ox, oy, scale)
	scale = scale or 1
	for _, part in ipairs(glyphs[id]) do
		if part[1] then
			local xx, yy = ox + part[1].x * scale, oy + part[1].y * scale
			for i = 2, #part do
				local x, y = ox + part[i].x * scale, oy + part[i].y * scale
				linedraw(grid, xx, yy, x, y)
				xx, yy = x, y
			end
		end
	end
end

local message = {}
local message_s =
"it's a meow MEOW =^^= world !! i hope you have a nice day. a wheeeeeeee meow why does that meow dissappear? I do not know. oh, i have to make it 72 cols wide i missed that so i am typing lots more text here entropyfilling aaaa don't guess me on this please sorry"
local space_value_from_outer_space = (" "):byte() - 32 + 12345
for c in message_s:gmatch(".") do message[#message + 1] = c:byte() - 32 + 12345 end
message[#message + 1] = space_value_from_outer_space

local ox, oy = space, linespace
local wormrowm = {}
local wormwormlen = 0

local function drawtotalwormrowm()
	local lll = 0
	for _, sworm in ipairs(wormrowm) do
		lll = lll + space * #sworm
	end
	local scabamgap = math.floor((width - lll - space) / (#wormrowm - 1))
	io.stderr:write(tostring(scabamgap) .. "\n")
	-- it's sligtly fucked
	for _, sworm in ipairs(wormrowm) do
		for _, id2 in ipairs(sworm) do
			glyphdraw(grid, id2, ox, oy)
			ox = ox + space
		end
		ox = ox + scabamgap
	end
	wormrowm = {}
	wormwormlen = space
	ox, oy = space, oy + linespace
end

local worm = {}
for _, id in ipairs(message) do
	if id ~= space_value_from_outer_space then
		worm[#worm + 1] = id
	else
		--nooonononono theree minutes to submisnitnoi
		--cant think
		-- -- it's  brokeorenn!!!
		local wl = (#worm + 1) * space
		if wormwormlen + wl > width then
			drawtotalwormrowm()
		else
			wormrowm[#wormrowm + 1] = worm
			wormwormlen = wormwormlen + wl
		end
		worm = {}
	end
end

drawtotalwormrowm()
--- iaaa it was the usuall silly last one not triggered issue this is really common in my programming

output(grid, width, height)

entry #6

comments 0

post a comment


cg106.el Unicode text, UTF-8 text
1
2
3
4
5
6
7
8
9
;; This buffer is for text that is not saved, and for Lisp evaluation.
;; To create a file, visit it with ‘C-x C-f’ and enter text in its buffer.

(defun cg106 (text)
  (with-temp-buffer
    (insert text)
    (setq fill-column 72)
    (fill-region (point-min) (point-max) 'full)
    (buffer-string)))

entry #7

comments 0

post a comment


submission.py ASCII text, with very long lines (885)
1
justify_and_print_string = lambda f: print((lambda j: "\n".join(j(p, j) for p in f.split("\n")))(lambda l, r: (l if len(l) == 72 else (lambda n: (r(l[:n], r) + '\n' + (lambda y: r(y, r) if len(y) > 72 else y.strip())(l[n:]) if n != 0 else r(l[:71] + "-", r) + "\n" + r(l[71:], r)))(max(l.rfind(" ", 0, 72), l.rfind("\n", 0, 72), 0))) if len(l) >= 72 else ((r((lambda i: l[:i] + " " + l[i:])((lambda i: i[2] - i[1] if len(i) == 3 else 0)(__import__("random").choice((sorted([(k, list(g)) for k, g in __import__("itertools").groupby(sorted(filter(lambda i: i[0], __import__("itertools").accumulate([(k, len(list(g))) for k, g in __import__("itertools").groupby(l,key=lambda c: c == " ")], lambda a, i: (i[0], i[1], (a[2] if len(a) == 3 else a[1]) + i[1]))), key=lambda i: i[1]), lambda i: i[1])], key=lambda g: g[0]) or [(0, [(False, 0, 0)])])[0][1]))).strip(), r) if " " in l else l))))