how can i align a text on words in autohotkey?
in the sample the text before the word quick and the word fox should be filled with spaces, so that alle words are vertical aligned.
oldtext =
(
a slow dog
the quick red fox
my quick brown and friendly fox
a quick yellow fox
a slow cat
the fox
)
newtext = TextAlign(oldtext, "quick")
newtext = TextAlign(newtext, "fox")
(
a slow dog
the quick red fox
my quick brown and friendly fox
a quick yellow fox
a slow cat
the fox
)
oldtext =
(
a slow dog
the quick red fox
my quick brown and friendly fox
a quick yellow fox
a slow cat
the fox
)
newtext := TextAlign(oldtext, "quick")
newtext := TextAlign(newtext, "fox")
clipboard:=newtext
TextAlign(text, x) {
lines := StrSplit(text, "`n", "`r")
For e, v in lines
CUR := v ~= "i)" x, MAX := (MAX < CUR ? CUR : Max)
for e, v in lines {
y := v ~= "i)" x, z := StrSplit(v, x)
newText .= ((y && y < max) ? (z[1] padSpaces(max - y) x z[2]) : v) "`n"
}
return newText
}
padSpaces(x) {
loop % x
r .= " "
return r
}
results:
a slow dog
the quick red fox
my quick brown and friendly fox
a quick yellow fox
a slow cat
the fox
thanks, my version is a little bit longer but it works too.
StrPad(str, padchar, padlen, left=1)
{
if (i := padlen-StrLen(str))
VarSetCapacity(w, i, asc(padchar)), NumPut(0, &w+i, "Char"), VarSetCapacity(w, -1)
return left ? w str : str w
}
TextAlign(data, xFind)
{
xpos:=0
data2:=""
Loop, Parse, data, `n, `r
{
line:=A_LoopField
pos := InStr(line, xFind, false)
if (pos > xpos)
{
xpos:=pos
}
}
Loop, Parse, data, `n, `r
{
line:=A_LoopField
pos := InStr(line, xFind, false)
if ( (pos > 0) AND (pos < xpos) )
{
xSpace:=StrPad(""," ",xpos-pos)
xRepl:=xSpace xFind
StringReplace, line, line, %xFind%, %xRepl%
data2:=data2 line "`n"
}
else
{
data2:=data2 line "`n"
}
}
return data2
}
Related
I'm looking for an algorithm that can be used to compare two sentences are provide a matching score. For example,
INPUT
Sentence Input 1: "A quick brown fox jumps over the lazy dog"
Sentence Input 2: "Alpha bravo dog quick beta gamma fox over the lazy dug"
OUTPUT
Output: "A quick brown fox jumps over the lazy dog"
Score: 5 out of 9 (words found in correct order)
Can someone please point me in the right direction?
Can you try this c++ based algorithm to solve the above problem?
int MatchingScore(string s1, string s2) {
int count = 0;
unordered_map<string, int> my_map;
stringstream ss1(s1);
stringstream ss2(s2);
vector<string> tokens1;
vector<string> tokens2;
string temp_str;
// tokenise strings s1, s2 based on space char
while(getline(ss1, temp_str, ' ')) {
tokens1.push_back(temp_str);
}
while(getline(ss2, temp_str, ' ')) {
tokens2.push_back(temp_str);
}
// push words of string1 to hash_map
for(auto s: tokens1) {
my_map[s]++;
}
// while iterating through string2 check if word already present in hash_map
for(auto s: tokens2) {
if(my_map.find(s) != my_map.end()) {
count++;
}
}
return count;
}
You can try this java code:
String sentence = "A quick brown fox jumps over the lazy dog";
String searchPhrase = "Alpha bravo dog quick beta gamma fox over the lazy dug";
String[] searchwords = searchPhrase.trim().split(" ");
int score = 0;
for (int i = 0; i<searchwords.length ;i++) {
if (sentence.toLowerCase().indexOf(searchwords[i].toLowerCase()) != -1) {
score +=1;
} else {
score +=0;
}
}
System.out.println("Score: " + score + " out of " + searchwords.length);
A working solution, Tested with variations. Need to be optimized with regex, etc
Output:
Score: 5 out of 9
A *quick* brown *fox* jumps *over* *the* *lazy* dog
Java code is written in Android Studio junit
String sentence = "A quick brown fox jumps over the lazy dog";
String searchPhrase = "Alpha bravo dog quick beta gamma fox over the lazy dug";
String[] searchWords = sentence.split(" ");
int score = 0;
String outputString = sentence;
for (String searchWord : searchWords) {
String spacedPhrase = " " + searchPhrase + " ";
String spacedWord = " " + searchWord.toLowerCase() + " ";
if (spacedPhrase.toLowerCase().contains(spacedWord)) {
score += 1;
searchPhrase = searchPhrase.substring(spacedPhrase.indexOf(spacedWord) + 1);
outputString = (" " + outputString + " ").replaceFirst(" "+ searchWord + " ",
" *" + searchWord + "* ");
}
}
System.out.println("Score: " + score + " out of " + sentence.split(" ").length);
System.out.println(outputString.trim());
assertEquals("A *quick* brown *fox* jumps *over* *the* *lazy* dog", outputString.trim());
I'm working on a text wrapping function. I want it to break a long line of text into string slices of a maximum length of characters. I've got it mostly working. However, sometimes the words are placed out of order.
This happens when there is a long word followed by a short word. I believe the program sees the longer word will not fit on the line so it skips that word and adds in the next word that will fit.
As this is text, the words must stay in the correct order. How can I force the loop to only add words in the correct order?
Actual Output:
[]string{" Go back out of the hotel entrance and your is", " room on lower ground a private street", " entrance."}
Expected Output:
[]string{" Go back out of the hotel entrance and your", " room is on lower ground a private street", " entrance."}
This is what I have so far.
Link: https://play.golang.org/p/YsCWoM9hQJV
package main
import (
"fmt"
"strings"
)
func main() {
directions := "Go back out of the hotel entrance and your room is on the lower ground a private street entrance."
ws := strings.Split(directions, " ")
neededSlices := strings.Count(directions, "") / 48
if strings.Count(directions, "")%48 != 0 {
neededSlices++
}
ls := make([]string, neededSlices, neededSlices)
keys := make(map[string]bool)
for i := 0; i < len(ls); i++ {
for _, v := range ws {
if _, ok := keys[v]; !ok {
if strings.Count(ls[i], "")+strings.Count(v, "") <= 48 {
ls[i] = ls[i] + " " + v
keys[v] = true
}
}
}
}
fmt.Printf("%#v", ls)
}
I think this is simple implementation of what you need
package main
import (
"fmt"
"strings"
)
func main() {
directions := "Go back out of the hotel entrance and your room is on the lower ground a private street entrance."
ws := strings.Split(directions, " ")
sl := []string{""}
i := 0
for _,word := range ws {
if (len(sl[i]) + len(word) + 1) >=48 {
i++
sl = append(sl, "")
}
sl[i] += " " + word
}
fmt.Printf("%#v", sl)
}
Link: https://play.golang.org/p/7R2TS6lv4Tm
The first problem I notice is your usage of a map. A map can only contain a key once. Due to this, your code will only contain each word once in one of the output slices.
The second problem is that you iterate over the whole ws array again for each iteration of the ls slice. I guess you tried to work around this issue with the map?
The solution would be to iterate only once over ws and assign the words to the index in ls.
Also note that strings.Count returns the number of characters (unicode points) in the string plus 1.
Your code btw also adds a space at the beginning of each string in the slice. I am not sure if this is intended (your expected output matches this). In my example solution I deviate from that so my output does not 100% match your stated expected output but I think it gives a more expected result.
package main
import (
"fmt"
"strings"
)
func main() {
directions := "Go back out of the hotel entrance and your hotel room is on the lower ground a private street entrance."
ws := strings.Split(directions, " ")
ls := []string{}
l := 0 // current line length
i := -1
for _, v := range ws {
lv := strings.Count(v, "")-1
if l == 0 || l+lv+1 > 48 {
i++
ls = append(ls, v)
l = lv
continue
}
ls[i] += " " + v
l += lv+1
}
fmt.Printf("%#v", ls)
}
Go Playground: https://play.golang.org/p/HhdX8RudiXn
I'm just wondering why these asian characters in this string wont show up when I reverse and print the individual characters in the string.
package main
import "fmt"
func main() {
a := "The quick brown 狐 jumped over the lazy 犬"
var lenght int = len(a) - 1
for ; lenght > -1; lenght-- {
fmt.Printf("%c", a[lenght])
}
fmt.Println()
}
You are accessing the string array by byte not by 'logical character'
To better understand this example breaks the string first as an array of runes and then prints the rune backwards.
http://play.golang.org/p/bzbo7k6WZT
package main
import "fmt"
func main() {
msg := "The quick brown 狐 jumped over the lazy 犬"
elements := make([]rune, 0)
for _, rune := range msg {
elements = append(elements, rune)
}
for i := len(elements) - 1; i >= 0; i-- {
fmt.Println(string(elements[i]))
}
}
Shorter Version: http://play.golang.org/p/PYsduB4Rgq
package main
import "fmt"
func main() {
msg := "The quick brown 狐 jumped over the lazy 犬"
elements := []rune(msg)
for i := len(elements) - 1; i >= 0; i-- {
fmt.Println(string(elements[i]))
}
}
I need to truncate a text to get a preview. The preview is the text prefix of ~N chars (but not more) and it should not split words in the middle.
preview("aaa", 10) = "aaa"
preview("a b c", 10) = "a b c"
preview("aaa bbb", 5) = "aaa"
preview("a b ccc", 3) = "a b"
I coded a function as follows:
def preview(s:String, n:Int) =
if (s.length <= n) s else s.take(s.lastIndexOf(' ', n))
Would you change or fix it ?
Now I am thinking how to handle the case when the text words are separated by one or more white spaces (including \n,\t, etc.) rather than just a single space. How would you improve the function to handle this case ?
How about the following:
def preview(s: String, n: Int) = if (s.length <= n) {
s
} else {
s.take(s.lastIndexWhere(_.isSpaceChar, n + 1)).trim
}
This function will:
For the strings shorter or equal n return the string (no preview required)
Otherwise find the the last space character in the n + 1 first characters (this will indicate whether the last world is being split, as if it's not than n + 1 will be a space chracter and otherwise a non-space character) and take a string up to this point
Note: The usage of isSpaceChar will not only provide support for space, but also new line or paragraph, which is what I believe you're after (and you can replace it with isWhitespace if you're after even more extended set of word separators).
I propose next one:
-- UPDATED--
def ellipsize(text : String, max : Int): String = {
def ellipsize0(s : String): String =
if(s.length <= max) s
else {
val end = s.lastIndexOf(" ")
if(end == -1) s.take(max)
else ellipsize0(s.take(end))
}
ellipsize0("\\s+".r.replaceAllIn(text, " "))
}
Or your (modified):
def preview(str : String, n : Int) = {
(s : String) => if (s.length <= n) s else s.take(s.lastIndexOf(' ', n))
}.apply( "\\s+".r.replaceAllIn(str, " "))
How about this
def preview(s:String, n:Int) =
if (s.length <= n) s
else s.take(n).takeWhile(_ != ' ')
Try it here: http://scalafiddle.net/console/a05d886123a54de3ca4b0985b718fb9b
This seems to work:
// find the last word that is not split by n, then take to its end
def preview(text: String, n: Int): String =
text take (("""\S+""".r findAllMatchIn text takeWhile (_.end <= n)).toList match {
case Nil => n
case ms => ms.last.end
})
An alternative take (pun intended) but doesn't like input of all whitespace:
text take (("""\S+""".r findAllMatchIn text takeWhile (m => m.start == 0 || m.end <= n)).toList.last.end min n)
Extensionally:
object Previewer {
implicit class `string preview`(val text: String) extends AnyVal {
// find the last word that is not split by n, then take to its end
def preview(n: Int): String =
text take (("""\S+""".r findAllMatchIn text takeWhile (_.end <= n)).toList match {
case Nil => n
case ms => ms.last.end
})
}
}
Looks nice that way:
class PreviewTest {
import Previewer._
#Test def shorter(): Unit = {
assertEquals("aaa", "aaa" preview 10)
}
#Test def spacey(): Unit = {
assertEquals("a b c", "a b c" preview 10)
}
#Test def split(): Unit = {
assertEquals("abc", "abc cba" preview 5)
}
#Test def onspace(): Unit = {
assertEquals("a b", "a b cde" preview 3)
}
#Test def trimming(): Unit = {
assertEquals("a b", "a b cde" preview 5)
}
#Test def none(): Unit = {
assertEquals(" " * 5, " " * 8 preview 5)
}
#Test def prefix(): Unit = {
assertEquals("a" * 5, "a" * 10 preview 5)
}
}
I am trying to insert a character into a string using Processing. After some reading around I tried out the following (I think Java) code:
1: String st = new String("abcde");
2: st = StringBuffer(st).insert(2, "C");
and got the following response:
the function StringBuffer(String) does not exist
Is there a different/simpler way of doing this? Do I need to use StringBuffer? I'm a fairly novice programmer so any help greatly appreciated.
Ok, so I've been looking at the processing 'Extended Language API' and there doesn't seem to be some function like that out of the box.
If you look at the String class's substring() function, you'll see an example where there is a String that is cut into two pieces at position 2. And then printed out with other characters between them. Will that help you any further?
String str1 = "CCCP";
String str2 = "Rabbit";
String ss1 = str1.substring(2); // Returns "CP"
String ss2 = str2.substring(3); // Returns "bit"
String ss3 = str1.substring(0, 2); // Returns "CC"
println(ss1 + ":" + ss2 + ":" + ss3); // Prints 'CP:bit:CC'
If we take your example, this would insert the 'C' at the right position:
String st = new String("abcde");
String p1 = st.substring(0,2); // "ab"
String p2 = st.substring(2); // "cde"
st = p1 + "C" + p2; // which will result in "abCcde"
Or create a function for it. Mind you, not super-robust (no checks for empty strings, overflow etc), but does the job:
String insert(original, toInsert, position){
String p1 = original.substring(0,position);
String p2 = original.substring(position);
return p1 + toInsert + p2;
}
...
String st = new String("abcde");
st = insert(st, "C", 2); // "abCcde"
st = insert(st, "D", 4); // "abCcDde"
tested at http://sketch.processing.org
You can insert multiple items with this functions by calling it once for each insert. To make it easier, insert them from right to left as otherwise the position to insert will change as you so inserts to the left.
Example:
String original="The quick fox jumped over lazy dog";
// lets insert "brown" at position 10, "the" at 21, and "'s back" at 34 to make
// "The quick brown fox jumped over the lazy dog's back"
println( original );
original= insertInString( original, "'s back", 34 );
original= insertInString( original, "the ", 26 );
original= insertInString( original, "brown ", 10 );
println( original );
This generated the following output:
The quick fox jumped over lazy dog
The quick brown fox jumped over the lazy dog's back
If you insert from left to right, the positions have to be adjusted after each insert.