How to find the distance between two runes - go

I'm trying to solve a couple of example programming problems to familiarize myself with the language.
I am iterating over a string as follows:
func main() {
fullFile := "abcdDefF"
for i := 1; i < len(fullFile); i++ {
println(fullFile[i-1], fullFile[i], fullFile[i-1]-fullFile[i])
}
}
In the loop I want to get the difference between the current rune and the previous rune (trying to identify lower-case - upper-case pairs by finding any pairs where the difference is == 32.
Strangely, the subtraction doesn't work properly (in fact seems to yield addition in cases where I would expect a negative number) although I would expect it to since runes are represented by int32.

Figured it out: the data type returned was a byte.
Explicitly converted to int and everything works as expected.
func main() {
fullFile, _ := ioutil.ReadFile("input/input.txt")
previous := 0
current := 0
for i := 1; i < len(fullFile); i++ {
previous = int(fullFile[i-1])
current = int(fullFile[i])
println(current, previous, current-previous)
}
}

Related

Sort an array with strings and numbers

I passed few hours searching about a lib or a way to do this:
I have an array []string{"ex10", "ex2", "ex1"} and after call the sort.Strings or using sort.Slice to compare with an array of bytes I get the result []string{"ex1", "ex10", "ex2"}
anyone has an idea how to implement this?
if anyone knows swift I've found the solution here
If you don't want the numbers sorted lexicographically, you need to separate them from the strings and parse them as integers.
This example assumes there is always a 2 letter prefix with a valid number, and slices the string accordingly: https://play.golang.org/p/LaX-pTr6etc
s := []string{"ex10", "ex2", "ex1"}
sort.Slice(s, func(i, j int) bool {
if s[i][:2] != s[j][:2] {
return s[i] < s[j]
}
ii, _ := strconv.Atoi(s[i][2:])
jj, _ := strconv.Atoi(s[j][2:])
return ii < jj
})

How can I identify a matching pattern for a given number using go?

I'm trying to identify pattern matches for a given telephone number range to use in a Cisco Communications Manager platform.
Essentially, an 'X' matches the numbers 0-9 in a telephone number, and you can specify a range of digits using the [x-y] notation.
Given a telephone number range of 02072221000-02072221149 consisting of 150 numbers, this would create and should output two patterns: 020722210XX and 020722211[0-4]X
Obviously I'd like it to work on any range provided. I just can't seem to get my head around how to generate those patterns given the number ranges.
Any thoughts would be greatly appreciated.
Many thanks.
I believe I found a decent algorithm which should handle this for you. I apologize ahead of time if any of the explanation isn't detailed enough, but a lot of this came to intuition which can be hard to explain.
I started with more simplified cases, figuring out a method for how to get the fewest number of patterns from a comparison. For my examples I'll be comparing 211234 to 245245.
After a bit of thinking I worked out that you need to take the range of numbers from the smaller number up to 9 and handle the special case for the lowest digit in the smaller number. To explain in a bit more detail, in the number 211234 the ideal is to represent the last digit as an X but we can only do that for cases where the digit may be [0-9] the only case in this example where we can't use [0-9] is when our tens digit is 3 because we have a lower limit of 4. This logic then propagates up the rest of the number as we head toward the most significant digit. So for the tens digit in the next case we have a lower bound based on the previous example of 4 because we're handling the case when we allow a 3 specially. So for our tens range we end up with a 4-9 because the next digit over does not restrict our range.
In fact we won't be restricted until the most significant digit which is bounded by the numbers in the range between the numbers we're comparing. After working a few problems out by hand I noticed a bit of a pattern of the pyramid of Xs in the cases where the numbers digits were significantly apart:
compare: 211234
to: 245245
21123[4-9]
2112[4-9]X
211[3-9]XX
21[2-9]XXX
2[2-3]XXXX
24[0-4]XXX
245[0-1]XX
2452[0-3]X
24514[0-5]
This was my first hint as to how to handle it. Starting from the least significant moving up, taking advantage of the symmetry, but handling the case where we hit the "top of the pyramid". This example is easy though, there are many corner cases which will cause issues. For the sake of brevity I'm not going to go into detail for each but I'll give a short explanation for each:
What do you do when the 2 compared digits has one number between them, such as between 4 and 6?
In this case simply use the single digit in place of a range.
What do you do when the 2 compared digits have no number between them, such as between 4 and 5?
In this case throw away the row in which you'd handle the numbers between the digits as all cases will be handled explicitly.
What do you do when the minimum number in the range is 8?
In this case when we add 1 to the number to get a lower bound for the range we get a 9, which means we can simply substitute in a 9 rather than a range of [9-9]
What do you do when the minimum number in the range is 9?
In this case we simply don't bother handling that number as when handling the next digit up it should be covered by its use of X
I'm sure I'm missing some corner cases which I handle in the code which I simply didn't think to put in this list. I'm willing to clarify any part of the code if you just leave a comment asking.
Below is my stab at it in Go. It could probably be a bit more DRY but this is what I came up with after fiddling for a bit. I'm also pretty new to Go so please notify me of any spirit fouls in the comments and I'll correct them.
I don't guarantee this will handle every case, but it handled every case I threw at it. It's up to you to turn it into a script which takes in 2 strings ;)
Edit: I just realized via the example in the question (which for some reason I never ran) that this doesn't always condense the provided range in to the smallest number of outputs, but it should always give patterns which cover every case. Despite this drawback I think it's a good step in the right direction for you to work on top of. I'll update the answer if I find the time to get it to condense cases where the previous range is 1-9 and the special case is 0. The best means for which might end up being after the initial generation condensing these cases "manually".
package main
import (
"strconv"
"fmt"
)
func getStringFromMinAndMax(min int, max int) (string, bool){
minstr := strconv.Itoa(min)
maxstr := strconv.Itoa(max)
if max == min {
return minstr, false
}
if max < min{
return minstr, false
}
return "["+minstr+"-"+maxstr+"]", true
}
func main(){
str1 := "211234"
str2 := "245245"
diffLength := 0
for i := 0; i < len(str1); i++{
diffLength = i+1
number1, _ := strconv.Atoi(str1[:len(str1)-i-1])
number2, _ := strconv.Atoi(str2[:len(str2)-i-1])
if number1 == number2 {
break
}
}
elems := (diffLength * 2)-1
output := make([]*[]string, elems+1)
for i := 0; i < elems; i++ {
newSlice := make([]string, diffLength)
output[i] = &newSlice
}
for digit := 0; digit < diffLength; digit++ {
for j := 0; j < diffLength; j++ {
if j == digit {
if output[j] != nil {
min, _ := strconv.Atoi(string(str1[len(str1)-(digit+1)]))
max := 9
if digit == diffLength-1 {
max, _ = strconv.Atoi(string(str2[len(str1)-(digit+1)]))
max = max - 1
}
if digit != 0{
min = min+1
}
if min < 10 {
maxchar := strconv.Itoa(max)[0]
minchar := strconv.Itoa(min)[0]
newVal, safe := getStringFromMinAndMax(min, max)
if digit == diffLength-1 && !safe && (str1[len(str1)-(digit+1)] == maxchar || str2[len(str2)-(digit+1)] == minchar) {
output[j] = nil
} else {
(*output[j])[diffLength-digit-1] = newVal
}
} else {
output[j] = nil
}
}
if j != diffLength-1 && output[elems-1-j] != nil {
min := 0
max, _ := strconv.Atoi(string(str2[len(str1)-(digit+1)]))
if digit != 0{
max = max-1
}
if max >= 0{
newVal, _ := getStringFromMinAndMax(min, max)
(*output[elems-1-j])[diffLength-digit-1] = newVal
} else {
output[elems-1-j] = nil
}
}
} else {
if j > digit {
if output[j] != nil {
(*output[j])[diffLength-digit-1] = "X"
}
if j != diffLength-1 && output[elems-1-j] != nil {
(*output[elems-1-j])[diffLength-digit-1] = "X"
}
} else {
if output[j] != nil {
(*output[j])[diffLength-digit-1] = string(str1[len(str1)-digit-1])
}
if j != diffLength-1 && output[elems-1-j] != nil {
(*output[elems-1-j])[diffLength-digit-1] = string(str2[len(str2)-digit-1])
}
}
}
}
}
for _, list := range output {
if list != nil{
if len(str1) != diffLength{
fmt.Printf(str1[:len(str1)-diffLength])
}
for _, element := range *list {
fmt.Printf(element)
}
fmt.Printf("\n")
}
}
}
Footnotes:
diffLength is the number of characters on the end of the strings which differ, I couldn't think of a better way to get this number than what's in the script...
Me setting an output to nil is me saying, "This one will be handled explicitly, so throw it away"
j is a variable for which output I'm setting... But this also gets mirrored to the bottom, so I couldn't think of a concise name to give it thus I left it j.
digit is tracking which digit from the right we are modifying

Adding/subtracting two numeric strings

I have two variables with big numbers set as strings:
var numA = "340282366920938463463374607431768211456"
var numB = "17014118346046923173168730371588410572"
I want to be able to add and subtract these kinds of large string numbers in Go.
I know I need to use math/big but I still can not for the life of me figure out how, so any example help will be greatly appreciated!
You may use big.NewInt() to create a new big.Int value initialized with an int64 value. It returns you a pointer (*big.Int). Alternatively you could simply use the builtin new() function to allocate a big.Int value which will be 0 like this: new(big.Int), or since big.Int is a struct type, a simple composite literal would also do: &big.Int{}.
Once you have a value, you may use Int.SetString() to parse and set a number given as string. You can pass the base of the string number, and it also returns you a bool value indicating if parsing succeeded.
Then you may use Int.Add() and Int.Sub() to calculate the sum and difference of 2 big.Int numbers. Note that Add() and Sub() write the result into the receiver whose method you call, so if you need the numbers (operands) unchanged, use another big.Int value to calculate and store the result.
See this example:
numA := "340282366920938463463374607431768211456"
numB := "17014118346046923173168730371588410572"
ba, bb := big.NewInt(0), big.NewInt(0)
if _, ok := ba.SetString(numA, 10); !ok {
panic("invalid numA")
}
if _, ok := bb.SetString(numB, 10); !ok {
panic("invalid numB")
}
sum := big.NewInt(0).Add(ba, bb)
fmt.Println("a + b =", sum)
diff := big.NewInt(0).Sub(ba, bb)
fmt.Println("a - b =", diff)
Output (try it on the Go Playground):
a + b = 357296485266985386636543337803356622028
a - b = 323268248574891540290205877060179800884

For loop of two variables in Go

The following for loop in Go isn't allowed,
for i := 0, j := 1; i < 10; i++, j++ {...}
What's the correct equivalent of the for-loop of two variables below?
for (int i = 0, j = 1; i < 10; i ++ , j ++) {...}
You don't have a comma operator to join multiple statements, but you do have multiple assignment, so this works:
package main
import (
"fmt"
)
func main() {
for i, j := 0, 1; i < 10; i, j = i+1, j+1 {
fmt.Println("Hello, playground")
}
}
Although above Answer is accepted, and it fully satisfy the need. But I would like to contribute some further explanation to it.
Golang Does not support many things which could be done in simple terms. For loop is a most common example of this. The beauty of Go's For loop is that it merges many modern style of looping into one keyword.
Similarly Golang do with Multiple Variable declaration and assignment. According to above mentioned problem, We could solve multi-variable for loop with this simple tool which Golang provides us. If you want to look into further explanation, this question provide further details and way of declaring multiple variables in one statement.
Coming back to for loop, If we want to declare variable of same datatype we can declare them with this
var a,b,c string
but we use short hand in for loop so we can do this for initializing them with same value
i,j := 0,1
Different Datatypes and Different Values
and if we want to declare different type of variables and want to assign different values we can do this by separating variables names and after := different values by comma as well. for example
c,i,f,b := 'c',23423,21.3,false
Usage of Assignment Operator
Later on, we can assign values to multiple variables with the same approach.
x,y := 10.3, 2
x,y = x+10, y+1
Mixing Struct and Normal types in single statement
Even we can use struct types or pointers the same way. Here is a function to iterate Linked list which is defined as a struct
func (this *MyLinkedList) Get(index int) int {
for i,list := 0,this; list != nil; i,list = i+1,list.Next{
if(i==index){
return list.Val
}
}
return -1
}
This list is defined as
type MyLinkedList struct {
Val int
Next *MyLinkedList
}
Answering to Original Problem
Coming to the origin Question, Simply it could be done
for i, j := 0, 1; i < 10; i, j = i+1, j+1 {
fmt.Println("i,j",i,j)
}
Suppose you want to loop using two different starting index, you can do this way.
This is the example to check if string is palindrome or not.
name := "naman"
for i<len(name) && j>=0{
if string(name[i]) == string(name[j]){
i++
j--
continue
}
return false
}
return true
This way you can have different stopping conditions and conditions will not bloat in one line.
As pointed by Mr. Abdul, for iterate among two variable you can use the following construct:
var step int = 4
for row := 0; row < rowMax; row++ {
for col := 0; col < colMax; col++ {
for rIndex, cIndex := row, col; rIndex <= row+step && cIndex <= col; rIndex, cIndex = rIndex+1, cIndex+1 {
}
}
}

Inverted Return from strings.Replace() Golang

I have a large dataset where I needed to do some string manipulation (I know strings are immutable). The Replace() function in the strings package does exactly what I need, except I need it to search in reverse.
Say I have this string: AA-BB-CC-DD-EE
Run this script:
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println(strings.Replace("AA-BB-CC-DD-EE", "-", "", 1))
}
It outputs: AABB-CC-DD-EE
What I need is: AA-BBCCDDEE, where the first instance of the search key is found, and the rest discarded.
Splitting the string, inserting the dash, and joining it back together works. But, I'm thinking there is a more performant way to achieve this.
String slices!
in := "AA-BB-CC-DD-EE"
afterDash := strings.Index(in, "-") + 1
fmt.Println(in[:afterDash] + strings.Replace(in[afterDash:], "-", "", -1))
(might require some tweaking to get the behavior you want in the case that the input has no dashes).
This can be another solution
package main
import (
"strings"
"fmt"
)
func Reverse(s string) string {
n := len(s)
runes := make([]rune, n)
for _, rune := range s {
n--
runes[n] = rune
}
return string(runes[n:])
}
func main() {
S := "AA-BB-CC-DD-EE"
S = Reverse(strings.Replace(Reverse(S), "-", "", strings.Count(S, "-")-1))
fmt.Println(S)
}
Another solution:
package main
import (
"fmt"
"strings"
)
func main() {
S := strings.Replace("AA-BB-CC-DD-EE", "-", "*", 1)
S = strings.Replace(S, "-", "", -1)
fmt.Println(strings.Replace( S, "*", "-", 1))
}
I think you want to use strings.Map rather than rigging things with compositions of functions. It's basically meant for this scenario: character replacement with more complex requirements than Replace and cousins can handle. The definition:
Map returns a copy of the string s with all its characters modified according to the mapping function. If mapping returns a negative value, the character is dropped from the string with no replacement.
Your mapping function can be built with a fairly simple closure:
func makeReplaceFn(toReplace rune, skipCount int) func(rune) rune {
count := 0
return func(r rune) rune {
if r == toReplace && count < skipCount {
count++
} else if r == toReplace && count >= skipCount {
return -1
}
return r
}
}
From there, it's a very straightforward program:
strings.Map(makeReplaceFn('-', 1), "AA-BB-CC-DD-EE")
Playground, this produces the desired output:
AA-BBCCDDEE
Program exited.
I'm not sure whether this is faster or slower than other solutions without benchmarking, because on one hand it has to call a function for each rune in the string, while on the other hand it doesn't have to convert (and thus copy) between a []byte/[]rune and string between each function call (though the subslicing answer by hobbs is probably overall the best).
In addition, the method can be easily adapted to other scenarios (e.g. retaining every other dash), with the caveat that strings.Map can only do rune to rune mapping, and not rune to string mapping like strings.Replace does.
This was a fun question to answer. While the solutions offered work neatly, splitting and replacing, to say nothing of calling Replace 3 times doesn't seem likely to be performant.
The answer? Don't reinvent the wheel, the go standard library has already almost solved this problem with Replace(), let's tweak it. I stumbled a bit over how the API of our new function should work, finally settling on leaving the signature unchanged, but deciding on minimal change from strings.Replace:
func ReplaceAfter(s,old,new string,skip int) string
The variable skip replaces n to clarify what it does since the caller will specify how many instances of old to skip replacing. skip==0 is defined as replacing every instance and skip==-1 is defined as replacing no instances.
From here there were really only a few bits of the function that needed changing.
func ReplaceAfter(s, old, new string, skip int) string {
if old == new || skip == -1 { // changed
return s // avoid allocation
}
// Compute number of replacements.
m := strings.Count(s, old)
if m == 0 || m < skip { // changed
return s // avoid allocation
} // changed (removed else if)
// Apply replacements to buffer.
n := m - skip // changed, n means the same thing but is calculated
t := make([]byte, len(s)+n*(len(new)-len(old))) // longer buffer
w := 0
start := 0
for i := 0; i < m; i++ {
j := start
if len(old) == 0 {
if i > 0 {
_, wid := utf8.DecodeRuneInString(s[start:])
j += wid
}
} else {
j += strings.Index(s[start:], old)
}
if i >= skip { // changed, replace
w += copy(t[w:], s[start:j])
w += copy(t[w:], new)
} else { // changed, skip ahead
w += copy(t[w:], s[start:j+len(old)])
}
start = j + len(old)
}
w += copy(t[w:], s[start:])
return string(t[0:w])
}
Here's a playground link with a working demo. If you're interested, I also copied and adapted the relevant Test functions from go/src/strings/, to make sure that the function as written behaved itself predictably.

Resources