Another update from ingydotnet^djgoku

This commit is contained in:
Ingy döt Net 2015-11-18 06:14:39 +00:00
parent 91df62d461
commit 948b86eafa
7604 changed files with 108452 additions and 22726 deletions

View file

@ -0,0 +1,35 @@
defmodule Align do
def columns(text, alignment) do
fieldsbyrow = String.split(text, "\n", trim: true)
|> Enum.map(fn line -> String.split(line, "$", trim: true) end)
maxfields = Enum.map(fieldsbyrow, fn field -> length(field) end) |> Enum.max
colwidths = Enum.map(fieldsbyrow, fn field -> field ++ List.duplicate("", maxfields - length(field)) end)
|> List.zip
|> Enum.map(fn column ->
Tuple.to_list(column) |> Enum.map(fn col-> String.length(col) end) |> Enum.max
end)
Enum.each(fieldsbyrow, fn row ->
Enum.zip(row, colwidths)
|> Enum.map(fn {field, width} -> adjust(field, width, alignment) end)
|> Enum.join(" ") |> IO.puts
end)
end
defp adjust(field, width, :Left), do: String.ljust(field, width)
defp adjust(field, width, :Right), do: String.rjust(field, width)
defp adjust(field, width, _), do: :string.centre(String.to_char_list(field), width)
end
text = """
Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.
"""
Enum.each([:Left, :Right, :Center], fn alignment ->
IO.puts "\n# #{alignment} Column-aligned output:"
Align.columns(text, alignment)
end)

View file

@ -36,33 +36,3 @@ prepare_line(Words_line, Words_length, Alignment) ->
Zipped = lists:zip (All_words, Words_length),
[ apply(string, Alignment, [Word, Length + 1, $\s])
|| {Word, Length} <- Zipped].
=== Output
1> c(align_columns).
{ok,align_columns}
2> align_columns:align_center().
Given a text file of many lines where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.
ok
3> align_columns:align_left().
Given a text file of many lines where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.
ok
4> align_columns:align_right().
Given a text file of many lines where fields within a line
are delineated by a single 'dollar' character, write a program
that aligns each column of fields by ensuring that words in each
column are separated by at least one space.
Further, allow for each word in a column to be either left
justified, right justified, or center justified within its column.
ok

View file

@ -0,0 +1,63 @@
(function (lines) {
var LEFT = 0,
CENTRE = 1,
RIGHT = 2;
return alignedTable(
lines.map(function (s) {
return s.split('$');
}),
2, // minimum gap between cols
LEFT // [LEFT|CENTRE|RIGHT] or [0|1|2]
)
// TABULATION OF RESULTS IN SPACED AND ALIGNED COLUMNS
// [s] -> n -> enum -> s
function alignedTable(lstRows, lngPad, iAlignment) {
// Max width of each column
var lstColWidths = range(0, lstRows.reduce(function (a, x) {
return x.length > a ? x.length : a;
}, 0) - 1).map(function (iCol) {
return lstRows.reduce(function (a, lst) {
var w = lst[iCol] ? lst[iCol].toString().length : 0;
return (w > a) ? w : a;
}, 0);
});
// Rows padded to equal width
return lstRows.map(function (lstRow) {
return lstRow.map(function (v, i) {
return align(v, lstColWidths[i] + lngPad, iAlignment);
}).join('')
}).join('\n');
}
// Text padded to left and/or right: aligned (left|centre|right)
// String, number of characters, alignment 0|1|2
// s -> n -> enum -> s
function align(s, n, a) {
var mid = (1 === a),
gap = n - s.length,
pad = Array(Math.floor((gap + 1) / (mid ? 2 : 1))).join(' ');
return (a ? pad + (!mid || gap % 2 ? '' : ' ') : '') + s +
(2 > a ? pad + (mid ? ' ' : '') : '');
}
// [m..n]
function range(m, n) {
return Array.apply(null, Array(n - m + 1)).map(function (x, i) {
return m + i;
});
}
})([
"Given$a$text$file$of$many$lines,$where$fields$within$a$line$",
"are$delineated$by$a$single$'dollar'$character,$write$a$program",
"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$",
"column$are$separated$by$at$least$one$space.",
"Further,$allow$for$each$word$in$a$column$to$be$either$left$",
"justified,$right$justified,$or$center$justified$within$its$column."
]);

View file

@ -0,0 +1,69 @@
package column_alignment
import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.nio.file.Paths
enum class Align_function {
LEFT {
override fun invoke(s: String, length: Int) = ("%-" + length + 's').format(("%" + s.length() + 's').format(s))
},
RIGHT {
override fun invoke(s: String, length: Int) = ("%-" + length + 's').format(("%" + length + 's').format(s))
},
CENTER {
override fun invoke(s: String, length: Int) = ("%-" + length + 's').format(("%" + ((length + s.length()) / 2) + 's').format(s))
};
abstract operator fun invoke(s: String, length: Int): String
}
/** Aligns fields into columns, separated by "|".
* @constructor Initializes columns aligner from lines in a list of strings.
* @property lines Lines in a single string. Empty string does form a column.
*/
class Column_aligner(val lines: List<String>) {
operator fun invoke(a: Align_function): String {
val result = StringBuilder()
for (lineWords in words) {
for (i in lineWords.indices) {
if (i == 0)
result.append('|')
result.append(a(lineWords[i], column_widths[i]))
result.append('|')
}
result.append('\n')
}
return result.toString()
}
private val words = arrayListOf<Array<String>>()
private val column_widths = arrayListOf<Int>()
init {
lines forEach {
val lineWords = java.lang.String(it).split("\\$")
words += lineWords
for (i in lineWords.indices)
if (i >= column_widths.size())
column_widths += lineWords[i].length()
else
column_widths[i] = Math.max(column_widths[i], lineWords[i].length())
}
}
}
fun main(args: Array<String>) {
if (args.size() < 1)
println("Usage: ColumnAligner file [L|R|C]")
else {
val ca = Column_aligner(Files.readAllLines(Paths.get(args[0]), StandardCharsets.UTF_8))
val alignment = if (args.size() >= 2) args[1] else "L"
when (alignment) {
"L" -> print(ca(Align_function.LEFT))
"R" -> print(ca(Align_function.RIGHT))
"C" -> print(ca(Align_function.CENTER))
else -> System.err.println("Error! Unknown alignment: " + alignment)
}
}
}

View file

@ -0,0 +1,18 @@
'''
cat <<'EOF' > align_columns.dat
Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.
EOF
'''
for align in '<^>':
rows = [ line.strip().split('$') for line in open('align_columns.dat') ]
fmts = [ '{:%s%d}' % (align, max( len(row[i]) if i < len(row) else 0 for row in rows ))
for i in range(max(map(len, rows))) ]
for row in rows:
print(' '.join(fmts).format(*(row + [''] * len(fmts))))
print('')

View file

@ -1,15 +1,13 @@
J2justifier = {'L' => :ljust,
'R' => :rjust,
'C' => :center}
J2justifier = {Left: :ljust, Right: :rjust, Center: :center}
=begin
Justify columns of textual tabular input where the record separator is the newline
and the field separator is a 'dollar' character.
justification can be L, R, or C; (Left, Right, or Centered).
justification can be Symbol; (:Left, :Right, or :Center).
Return the justified output as a string
=end
def aligner(infile, justification = 'L')
def aligner(infile, justification = :Left)
fieldsbyrow = infile.map {|line| line.strip.split('$')}
# pad to same number of fields per record
maxfields = fieldsbyrow.map(&:length).max
@ -38,8 +36,8 @@ Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.
END
for align in %w{Left Right Center}
for align in [:Left, :Right, :Center]
infile = StringIO.new(textinfile)
puts "\n# %s Column-aligned output:" % align
puts aligner(infile, align[0..0])
puts aligner(infile, align)
end

View file

@ -1,53 +1,46 @@
#![feature(core)]
extern crate core;
use core::iter::repeat;
use core::str::StrExt;
use std::iter::Extend;
use std::iter::{Extend, repeat};
enum AlignmentType { Left, Center, Right }
fn get_column_widths(text: &str) -> Vec<usize> {
let mut widths = Vec::new();
for line in text.lines().map(|s| s.trim_matches(' ').trim_right_matches('$')) {
let mut lens = line.split('$').map(|s| s.char_len());
let mut idx = 0;
for len in lens {
if idx < widths.len() {
widths[idx] = std::cmp::max(widths[idx], len);
}
else {
widths.push(len);
}
idx += 1;
}
}
widths
let mut widths = Vec::new();
for line in text.lines().map(|s| s.trim_matches(' ').trim_right_matches('$')) {
let lens = line.split('$').map(|s| s.chars().count());
for (idx, len) in lens.enumerate() {
if idx < widths.len() {
widths[idx] = std::cmp::max(widths[idx], len);
}
else {
widths.push(len);
}
}
}
widths
}
fn align_columns(text: &str, alignment: AlignmentType) -> String {
let widths = get_column_widths(text);
let mut result = String::new();
for line in text.lines().map(|s| s.trim_matches(' ').trim_right_matches('$')) {
for (s, w) in line.split('$').zip(widths.iter()) {
let blank_count = w - s.char_len();
let (pre, post) = match alignment {
AlignmentType::Left => (0, blank_count),
AlignmentType::Center => (blank_count / 2, (blank_count + 1) / 2),
AlignmentType::Right => (blank_count, 0),
};
result.extend(repeat(' ').take(pre));
result.push_str(s);
result.extend(repeat(' ').take(post));
result.push(' ');
}
result.push_str("\n");
}
result
let widths = get_column_widths(text);
let mut result = String::new();
for line in text.lines().map(|s| s.trim_matches(' ').trim_right_matches('$')) {
for (s, w) in line.split('$').zip(widths.iter()) {
let blank_count = w - s.chars().count();
let (pre, post) = match alignment {
AlignmentType::Left => (0, blank_count),
AlignmentType::Center => (blank_count / 2, (blank_count + 1) / 2),
AlignmentType::Right => (blank_count, 0),
};
result.extend(repeat(' ').take(pre));
result.push_str(s);
result.extend(repeat(' ').take(post));
result.push(' ');
}
result.push_str("\n");
}
result
}
fn main() {
let text = r#"Given$a$text$file$of$many$lines,$where$fields$within$a$line$
let text = r#"Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.

View file

@ -12,7 +12,7 @@ SET nix=SPLIT (exampletext,":$:",c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12)
LOOP l1=1,12
SET colum=CONCAT ("c",l1)
SET newcolum=CONCAT ("new",l1)
SET @newcolum="", length=MAX LENGTH (@colum), space=length+2
SET @newcolum="", length=MAX LENGTH (@colum), space=length+2
LOOP n,l2=@colum
SET newcell=CENTER (l2,space)
SET @newcolum=APPEND (@newcolum,"~",newcell)

View file

@ -1,6 +1,4 @@
Module Module1
Private Delegate Function Justification(s As String, width As Integer) As String
Private Function AlignColumns(lines As String(), justification As Justification) As String()