2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -1,41 +1,30 @@
/*REXX program finds the best shuffle (for any list of words (characters). */
parse arg @ /*get some words from the command line.*/
if @='' then @ = 'tree abracadabra seesaw elk grrrrrr up a' /*use default? */
w=0 /*width of the longest word; for output*/
do i=1 for words(@) /* [↓] process all the words in list. */
w=max(w, length(word(@, i))) /*set the maximum word width (so far). */
end /*i*/ /* [↑] ··· finds the widest word in @.*/
w=w+9 /*add 9 blanks, the output looks nicer.*/
do n=1 for words(@) /*process all the words in the @ list. */
$=word(@,n) /*get the original word in the @ list. */
new=bestShuffle($) /*get a shufflized version of the word.*/
say 'original:' left($,w) 'new:' left(new,w) 'count:' kSame($,new)
/*REXX program determines and displays the best shuffle for any list of words/characters*/
parse arg $ /*get some words from the command line.*/
if $='' then $= 'tree abracadabra seesaw elk grrrrrr up a' /*use the defaults?*/
w=0; #=words($) /* [↑] finds the widest word in $ list*/
do i=1 for #; @.i=word($,i); w=max(w, length(@.i) ); end /*i*/
w=w+9 /*add 9 blanks for output indentation. */
do n=1 for #; new=bestShuffle(@.n) /*process the examples in the @ array. */
same=0; do m=1 for length(@.n)
same=same + (substr(@.n, m, 1) == substr(new, m, 1) )
end /*m*/
say 'original:' left(@.n, w) 'new:' left(new,w) 'count:' same
end /*n*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────BESTSHUFFLE subroutine────────────────────*/
bestShuffle: procedure; parse arg x 1 ox; Lx=length(x)
if Lx<3 then return reverse(x) /*fast track these small # of puppies. */
do j=1 for Lx-1; jp=j+1 /* [↓] handle any possible replicates.*/
a=substr(x,j ,1)
b=substr(x,j+1,1); if a\==b then iterate /*ignore replicates.*/
_=verify(x,a); if _==0 then iterate /*switch 1st replicate with some char. */
y=substr(x,_,1); x=overlay(a,x,_)
x=overlay(y,x,j)
rx=reverse(x); _=verify(rx,a); if _==0 then iterate /*¬enough uniqueness*/
y=substr(rx,_,1); _=lastpos(y,x) /*switch 2nd replicate with later char.*/
x=overlay(a,x,_); x=overlay(y,x,jp) /*OVERLAYs: a fast way to swap chars. */
end /*j*/
do k=1 for Lx /*handle cases of possible replicates. */
a=substr( x,k,1)
b=substr(ox,k,1); if a\==b then iterate /*skip replicate. */
if k==Lx then x=left(x,k-2)a || substr(x,k-1,1) /*handle last case*/
else x=left(x,k-1)substr(x,k+1,1)a || substr(x,k+2)
end /*k*/
return x
/*──────────────────────────────────KSAME procedure───────────────────────────*/
kSame: procedure; parse arg x,y; k=0
do m=1 for min(length(x), length(y)); k=k + (substr(x,m,1) == substr(y,m,1))
end /*m*/
return k
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
bestShuffle: procedure; parse arg x 1 ox; L=length(x); if L<3 then return reverse(x)
/*[↑] fast track short strs*/
do j=1 for L-1; parse var x =(j) a +1 b +1 /*get A,B at Jth & J+1 pos.*/
if a\==b then iterate /*ignore any replicates. */
c=verify(x,a); if c==0 then iterate /* " " " */
x=overlay( substr(x,c,1), overlay(a,x,c), j) /*swap the x,c characters*/
rx=reverse(x) /*obtain the reverse of X. */
y=substr(rx, verify(rx,a), 1) /*get 2nd replicated char. */
x=overlay(y, overlay(a,x, lastpos(y,x)),j+1) /*fast swap of 2 characters*/
end /*j*/
do k=1 for L; a=substr(x,k,1) /*handle a possible rep. */
if a\==substr(ox,k,1) then iterate /*skip non-replications*/
if k==L then x=left(x,k-2)a || substr(x,k-1,1) /*last case*/
else x=left(x,k-1)substr(x,k+1,1)a || substr(x, k+2)
end /*k*/
return x

View file

@ -0,0 +1,135 @@
extern crate permutohedron;
extern crate rand;
use std::cmp::{min, Ordering};
use std::env;
use rand::{thread_rng, Rng};
use std::str;
const WORDS: &'static [&'static str] = &["abracadabra", "seesaw", "elk", "grrrrrr", "up", "a"];
#[derive(Eq)]
struct Solution {
original: String,
shuffled: String,
score: usize,
}
// Ordering trait implementations are only needed for the permutations method
impl PartialOrd for Solution {
fn partial_cmp(&self, other: &Solution) -> Option<Ordering> {
match (self.score, other.score) {
(s, o) if s < o => Some(Ordering::Less),
(s, o) if s > o => Some(Ordering::Greater),
(s, o) if s == o => Some(Ordering::Equal),
_ => None,
}
}
}
impl PartialEq for Solution {
fn eq(&self, other: &Solution) -> bool {
match (self.score, other.score) {
(s, o) if s == o => true,
_ => false,
}
}
}
impl Ord for Solution {
fn cmp(&self, other: &Solution) -> Ordering {
match (self.score, other.score) {
(s, o) if s < o => Ordering::Less,
(s, o) if s > o => Ordering::Greater,
_ => Ordering::Equal,
}
}
}
fn _help() {
println!("Usage: best_shuffle <word1> <word2> ...");
}
fn main() {
let args: Vec<String> = env::args().collect();
let mut words: Vec<String> = vec![];
match args.len() {
1 => {
for w in WORDS.iter() {
words.push(String::from(*w));
}
}
_ => {
for w in args.split_at(1).1 {
words.push(w.clone());
}
}
}
let solutions = words.iter().map(|w| best_shuffle(w)).collect::<Vec<_>>();
for s in solutions {
println!("{}, {}, ({})", s.original, s.shuffled, s.score);
}
}
// Implementation iterating over all permutations
fn _best_shuffle_perm(w: &String) -> Solution {
let mut soln = Solution {
original: w.clone(),
shuffled: w.clone(),
score: w.len(),
};
let w_bytes: Vec<u8> = w.clone().into_bytes();
let mut permutocopy = w_bytes.clone();
let mut permutations = permutohedron::Heap::new(&mut permutocopy);
while let Some(p) = permutations.next_permutation() {
let hamm = hamming(&w_bytes, p);
soln = min(soln,
Solution {
original: w.clone(),
shuffled: String::from(str::from_utf8(p).unwrap()),
score: hamm,
});
// Accept the solution if score 0 found
if hamm == 0 {
break;
}
}
soln
}
// Quadratic implementation
fn best_shuffle(w: &String) -> Solution {
let w_bytes: Vec<u8> = w.clone().into_bytes();
let mut shuffled_bytes: Vec<u8> = w.clone().into_bytes();
// Shuffle once
let sh: &mut [u8] = shuffled_bytes.as_mut_slice();
thread_rng().shuffle(sh);
// Swap wherever it doesn't decrease the score
for i in 0..sh.len() {
for j in 0..sh.len() {
if (i == j) | (sh[i] == w_bytes[j]) | (sh[j] == w_bytes[i]) | (sh[i] == sh[j]) {
continue;
}
sh.swap(i, j);
break;
}
}
let res = String::from(str::from_utf8(sh).unwrap());
let res_bytes: Vec<u8> = res.clone().into_bytes();
Solution {
original: w.clone(),
shuffled: res,
score: hamming(&w_bytes, &res_bytes),
}
}
fn hamming(w0: &Vec<u8>, w1: &Vec<u8>) -> usize {
w0.iter().zip(w1.iter()).filter(|z| z.0 == z.1).count()
}