June 2018 Update

This commit is contained in:
Ingy döt Net 2018-06-22 20:57:24 +00:00
parent ba8067c3b7
commit 22f33d4004
5278 changed files with 84726 additions and 14379 deletions

View file

@ -0,0 +1,36 @@
# Project : Best shuffle
# Date : 2018/02/15
# Author : Gal Zsolt (~ CalmoSoft ~)
# Email : <calmosoft@gmail.com>
test = ["abracadabra", "seesaw", "elk", "grrrrrr", "up", "a"]
for n = 1 to len(test)
bs = bestshuffle(test[n])
count = 0
for p = 1 to len(test[n])
if substr(test[n],p,1) = substr(bs,p,1)
count = count + 1
ok
next
see test[n] + " -> " + bs + " " + count + nl
next
func bestshuffle(s1)
s2 = s1
for i = 1 to len(s2)
for j = 1 to len(s2)
if (i != j) and (s2[i] != s1[j]) and (s2[j] != s1[i])
if j < i
i1 = j
j1 = i
else
i1 = i
j1 = j
ok
s2 = left(s2,i1-1) + substr(s2,j1,1) + substr(s2,i1+1,(j1-i1)-1) + substr(s2,i1,1) + substr(s2,j1+1)
ok
next
next
bestshuffle = s2
return bestshuffle

View file

@ -0,0 +1,36 @@
def best_shuffle(s)
# Fill _pos_ with positions in the order
# that we want to fill them.
pos = []
# g["a"] = [2, 4] implies that s[2] == s[4] == "a"
g = s.length.times.group_by { |i| s[i] }
# k sorts letters from low to high count
k = g.sort_by { |k, v| v.length }.map { |k, v| k }
until g.empty?
k.each do |letter|
g[letter] or next
pos.push(g[letter].pop)
g[letter].empty? and g.delete letter
end
end
# Now fill in _new_ with _letters_ according to each position
# in _pos_, but skip ahead in _letters_ if we can avoid
# matching characters that way.
letters = s.dup
new = "?" * s.length
until letters.empty?
i, p = 0, pos.pop
i += 1 while letters[i] == s[p] and i < (letters.length - 1)
new[p] = letters.slice! i
end
score = new.chars.zip(s.chars).count { |c, d| c == d }
[new, score]
end
%w(abracadabra seesaw elk grrrrrr up a).each do |word|
puts "%s, %s, (%d)" % [word, *best_shuffle(word)]
end

View file

@ -0,0 +1,25 @@
list$ = "abracadabra seesaw pop grrrrrr up a"
while word$(list$,ii + 1," ") <> ""
ii = ii + 1
w$ = word$(list$,ii," ")
bs$ = bestShuffle$(w$)
count = 0
for i = 1 to len(w$)
if mid$(w$,i,1) = mid$(bs$,i,1) then count = count + 1
next i
print w$;" ";bs$;" ";count
wend
function bestShuffle$(s1$)
s2$ = s1$
for i = 1 to len(s2$)
for j = 1 to len(s2$)
if (i <> j) and (mid$(s2$,i,1) <> mid$(s1$,j,1)) and (mid$(s2$,j,1) <> mid$(s1$,i,1)) then
if j < i then i1 = j:j1 = i else i1 = i:j1 = j
s2$ = left$(s2$,i1-1) + mid$(s2$,j1,1) + mid$(s2$,i1+1,(j1-i1)-1) + mid$(s2$,i1,1) + mid$(s2$,j1+1)
end if
next j
next i
bestShuffle$ = s2$
end function

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()
}