So my friend gave me this task where the sum of squares of positive numbers must be calculated using recursion.
Conditions - The input will be a string with space separated numbers
This is what I've come so far but this shows a runtime error.
Here is the full error https://ideone.com/53oOjN
package main
import(
'fmt',
'strings',
'strconv'
)
var n int = 4
var sum_of_squares int = 0
func sumOfSquares(strArray []string, iterate int) int{
number, _ := strconv.Atoi(strArray[iterate])
if number > 0 {
sum_of_squares += number*number
}
if iterate == n {
return 0 // just to end the recursion
}
return sumOfSquares(strArray, iterate+1)
}
func main() {
str := "1 2 3 4"
strArray := strings.Fields(str)
result := sumOfSquares(strArray, 0)
fmt.Println(sum_of_squares, result)
}
The rule of thumb in recursion is termination condition. It should exist and it should exist in the right place.
func sumOfSquares(strArray []string, iterate int) int{
if iterate >= len(strArray) {
return sum_of_squares
}
number, _ := strconv.Atoi(strArray[iterate]) //TODO: handle err here
sum_of_squares += number*number
return sumOfSquares(strArray, iterate+1)
}
Just for you information: canonical recursion should not save it's state into global fields. I would suggest using following function signature.
func sumOfSquares(strArray []string, iterate, currentSum int) int{
//...
return sumOfSquares(strArray, iterate+1, sum_of_squares)
}
So that you don't need to store sum_of_squares somewhere. You will just pass it to next function invocation.
package main
import (
"fmt"
"strconv"
"strings"
)
var n int
func sumOfSquares(strArray []string, iterate int) int {
number, _ := strconv.Atoi(strArray[iterate])
if iterate == n {
return number * number
}
return ((number * number) + sumOfSquares(strArray, iterate+1))
}
func main() {
str := "1 2 3 4"
strArray := strings.Fields(str)
n = len(strArray) - 1
result := sumOfSquares(strArray, 0)
fmt.Println(result)
}
Indexing starts from 0, so decrease the length by one.
As #peterSO have pointed out, if strings contain unusual characters, it doesn't work, I didn't post the right answer for getting input because you seem to be beginner, but you can read the input, like this instead.
var inp []byte
var loc int
inp, _ = ioutil.ReadFile(fileName)
//add \n so that we don't end up running out of bounds,
//if last byte is integer.
inp = append(inp, '\n')
func scanInt() (res int) {
if loc < len(inp) {
for ; inp[loc] < 48 || inp[loc] > 57; loc++ {
}
for ; inp[loc] > 47 && inp[loc] < 58; loc++ {
res = res<<3 + res<<1 + (int(inp[loc]) - 48)
}
}
return
}
This is faster and scans integers only, and skips all other unusual characters.
I like to keep it simple. I have some few if conditions as well, but hope you like it.
func sumOfSquares(numArr []string) int {
i, err := strconv.Atoi(numArr[0])
rest := numArr[1:]
//Error checking
if err != nil {
fmt.Println(err)
os.Exit(1)
return 0
}
square := i * i
// negative & last number
if i < 0 && len(rest) == 0 {
return square
}
// negative & not last number
if i < 0 && len(rest) > 0 {
return sumOfSquares(rest)
}
// last man standing
if i >= 0 && len(rest) == 0 {
return square
}
return square + sumOfSquares(rest)
}
DEMO : https://play.golang.org/p/WWYxKbvzanJ
Related
I have problem for sorting my array in Go,
Here is my code :
func main() {
fmt.Print("Masukkan Jumlah Data yang akan dimasukkan: ")
var jumlahdata int
fmt.Scanln(&jumlahdata)
var DataDiagram = make([]int, jumlahdata)
fmt.Print("Masukkan data secara berurutan dengan spasi sebagai pemisah antar angka: ")
for i := 0; i < jumlahdata; i++ {
fmt.Scanf("%d", &DataDiagram[i])
}
fmt.Print("\n")
var max int = DataDiagram[0]
for _, value := range DataDiagram { // Menemukan nilai maximum
if value > max {
max = value
}
}
var mem int
Sorting(DataDiagram, jumlahdata, mem, max)
}
func Grafik(jumlahdata int, max int, DataDiagram []int) {
for i := max; i >= 1; i-- { // membuat Data Diagram
for j := 0; j < jumlahdata; j++ {
if DataDiagram[j] >= i {
fmt.Print(" | ")
} else {
fmt.Print(" ")
}
}
fmt.Print("\n")
}
for i := 0; i < jumlahdata; i++ {
fmt.Print("---")
}
fmt.Print("\n")
fmt.Print(" ")
for i := 0; i < jumlahdata; i++ {
fmt.Print(DataDiagram[i], " ")
}
}
func Sorting(DataDiagram []int, jumlahdata int, mem int, max int) {
for langkah := 0; langkah < (jumlahdata-1) ; langkah++ {
Grafik(jumlahdata, max, DataDiagram)
for i := 0; i < jumlahdata - (langkah-1); i++ {
if DataDiagram[i] > DataDiagram[i + 1] {
mem := DataDiagram[i];
DataDiagram[i] = DataDiagram[i + 1]
DataDiagram[i + 1] = mem;
}
}
}
}
What i expect is look like this:
What I Expect
But the output said otherwise, it give me error : It give me error
Can someone give some guide how to fix this :) i just learn Go yesterday, it similiar to C, but keep giving me index out of range error
I understand your task is to sort an int "array" (slice, in go-speak), showing each step of your work as a graph. Because you must show your work, you can't use go's built-in sorting, e.g. sort.Ints(DataDiagram).
Your problems are with the Sorting function.
Step 1 Your immediate crash-causing problem is that i eventually iterates to a number larger than upper index of DataDiagram. That we fix in the commented line below.
// Step 1: fix the iterator
func Sorting(DataDiagram []int, jumlahdata int, mem int, max int) {
for langkah := 0; langkah < (jumlahdata-1) ; langkah++ {
Grafik(jumlahdata, max, DataDiagram)
for i := 0; i < jumlahdata - 1; i++ { // Was: for i := 0; i < jumlahdata - (langkah-1); i++ {
if DataDiagram[i] > DataDiagram[i + 1] {
mem := DataDiagram[i];
DataDiagram[i] = DataDiagram[i + 1]
DataDiagram[i + 1] = mem;
}
}
}
}
Step 2 The code no longer crashes, but is not guaranteed to sort, because it makes only one pass through the inputs. We need to continue looping until there's no more swapping taking place. That problem is fixed below. The code now produces the expected output on the playground.
// Step 2: loop until sorted
func Sorting(DataDiagram []int, jumlahdata int, mem int, max int) {
swapped := true
for swapped {
Grafik(jumlahdata, max, DataDiagram)
swapped = false
for i := 0; i < jumlahdata - 1; i++ {
if DataDiagram[i] > DataDiagram[i + 1] {
mem := DataDiagram[i];
DataDiagram[i] = DataDiagram[i + 1]
DataDiagram[i + 1] = mem;
swapped = true
}
}
}
}
Step 3 The above code works fine, but perhaps can use some tidying. The end result is unchanged on the playground.
// Step 3: make it prettier
func Sorting(data []int) {
max := data[0]
for _, value := range data { // Menemukan nilai maximum
if value > max {
max = value
}
}
swapped := true
for swapped {
Grafik(len(data), max, data)
swapped = false
for i := 0; i < len(data)-1; i++ {
if data[i] > data[i+1] {
data[i], data[i+1] = data[i+1], data[i]
swapped = true
}
}
}
}
It's much simpler if you would just use
sort.Ints(ints), which you can see here:
https://goplay.space/#i9VIrDG-vL-
I want to convert a variable (I took an int for this example) to a byte using this code that I have found:
func IntToByteArray(num int64) []byte {
size := int(unsafe.Sizeof(num))
arr := make([]byte, size)
for i := 0 ; i < size ; i++ {
byt := *(*uint32)(unsafe.Pointer(uintptr(unsafe.Pointer(&num)) + uintptr(i)))
arr[i] = byte(byt)
}
return arr
}
func main(){
println(IntToByteArray(1456))
}
But the output that it gives me is this one : [8/8]0xc00001a0d0
Can some one explain me why do I have this has a result?
And what is exactly a byte array?
package main
import "fmt"
func IntToByteArray(num int64) []byte {
r := make([]byte, 8)
for i := 0; i < len(r); i++ {
r[i] = byte(num >> (i * 8) & 255)
}
return r
}
func main() {
fmt.Println(IntToByteArray(65280))
}
This assumes little-endianness.
As others have suggested, the included packages are more flexible and tested.
I wonder why my solution to this LeetCode "Move Zeros" problem is slower than the majority of other submissions. Is there a better way to approach this problem to make it faster?
The question is as follows:
Given an array nums, write a function to move all 0's to the end of it while maintaining the relative order of the non-zero elements. You must do this in-place without making a copy of the array.
Example:
Input: [0,1,0,3,12]
Output: [1,3,12,0,0]
This is my solution:
func moveZeroes(_ nums: inout [Int]) {
var index = 0
for (i,n) in nums.enumerated()
{
if n != 0
{
nums[index] = n
index += 1
}
}
while index < nums.count
{
nums[index] = 0
index += 1
}
}
LeetCode gives me these statistics:
Runtime: 52 ms, faster than 40.50% of Swift online submissions for Move Zeroes.
Memory Usage: 19.4 MB, less than 13.33% of Swift online submissions for Move Zeroes.
EDIT 1:
If I approach the problem as follows, it does not move the zeros at the end,
EDIT 2:
Here is 36ms in-place solution for you :
class Solution {
func moveZeroes(_ nums: inout [Int]) {
if nums.count < 2 {
return
}
var j = 0
while j < nums.count, nums[j] != 0 {
j += 1
}
if j < nums.count - 1 {
for i in j+1..<nums.count {
if nums[i] != 0 {
nums.swapAt(i, j)
j += 1
}
}
}
}
}
From what I can see, it's likely other submissions are doing this
Check and count 0's in string
Remove 0's
Replace number of 0's at the end of the string
A logical method no doubt, but I'd say yours just picks the basic needs of the challenge and goes for it.
I would personally use:
input = input.filter { $0 != 0 } + input.filter { $0 == 0 }
which can be simplified to one pass:
let nonZeros = input.filter { $0 != 0 }
input = nonZeros + Array(repeating: 0, count: input.count - nonZeros.count)
EDIT: The simplest version without creating a new array would be some primitive version of bubble sort, e.g.:
var numZeros = 0
// iterate array from start to end
for (offset, element) in input.enumerated() {
if element == 0 {
// count every zero
numZeros += 1
} else if numZeros > 0 {
// move every non-zero element left
input[offset - numZeros] = element
// replace with zero
input[offset] = 0
}
}
Another approach is the half-stable-partition algorithm. The benefit is the items are swapped rather than removed and inserted/appended.
Half-stable means the order of the left side of the split point is preserved.
extension Array {
mutating func halfStablePartition(indexes : IndexSet) { // code is O(n)
guard var i = indexes.first, i < count else { return }
var j = index(after: i)
var k = indexes.integerGreaterThan(i) ?? endIndex
while j != endIndex {
if k != j { swapAt(i, j); formIndex(after: &i) }
else { k = indexes.integerGreaterThan(k) ?? endIndex }
formIndex(after: &j)
}
}
}
var input = [0,1,0,3,12]
let indices = IndexSet(input.indices.filter{input[$0] == 0})
input.halfStablePartition(indexes: indices)
Swift 4.2 or later using removeAll mutating method:
Mutating the input:
class Solution {
func moveZeroes(_ nums: inout [Int]) {
var counter = 0
nums.removeAll {
if $0 == 0 {
counter += 1
return true
}
return false
}
nums += repeatElement(0, count: counter)
}
}
A similar approach for Swift 4.1 or earlier
func moveZeroes(_ nums: inout [Int]) {
var counter = 0
nums.indices.reversed().forEach {
if nums[$0] == 0 {
counter += 1
nums.remove(at: $0)
}
}
nums += repeatElement(0, count: counter)
}
var input = [0,1,0,3,12]
moveZeroes(&input)
input // [1, 3, 12, 0, 0]
Non mutating approach:
func moveZeroes(_ nums: [Int]) -> [Int] {
var counter = 0
return nums.filter {
if $0 == 0 { counter += 1 }
return $0 != 0
} + repeatElement(0, count: counter)
}
let input = [0,1,0,3,12]
let zerosMoved = moveZeroes(input)
zerosMoved // [1, 3, 12, 0, 0]
For modifying array in place, and keeping it:
O(n) for Time Complexity
O(1) for Space Complexity
Cracked my head way to long for this one. The cleanest way if you swap element that is NOT zero:
func moveZeroes(_ nums: inout [Int]) {
// amount of swaps, will be used a as reference for next swap index
var j = 0
for (i, e) in nums.enumerated() {
if e != 0 {
nums.swapAt(j, i)
j += 1
}
}
}
One fast solution is to shift non-zero elements to the left by the amount of zeros encountered until then:
func moveZeroes(_ nums: inout [Int]) {
var offset = 0
for i in 0..<nums.count {
if nums[i] == 0 { offset += 1 }
else { nums.swapAt(i, i-offset) }
}
}
This solution takes exactly N steps, and at each step we either perform an addition, or a swap, which are both quite fast.
Your solution, on the other hand required two iterations, resulting in 2*N steps, which is why it was slower than other solutions.
My code won't run properly I am trying to get it to find peaks including the end and beginning of the array and then compare all the indexes that aren't the beginning or end to the index before and after them does anyone know why I am getting the out of index range error?
package main
import "fmt"
func linearFindPeaks(arg []int) []int {
peaks := []int{}
lenArg := len(arg)
for i := 0; i < lenArg; i++ {
//if its the first element run this
//second if statement for the end of array
// for default statements
if arg[0] > arg[1] {
peaks = append(peaks, arg[0])
} else if arg[lenArg-1] > arg[lenArg-2] {
peaks = append(peaks, arg[lenArg-1])
} else if arg[i] > arg[i+1] && arg[i] > arg[i-1] && arg[i] != arg[0] && arg[i] != arg[lenArg-1] {
peaks = append(peaks, arg[i])
}
}
fmt.Println(peaks)
return peaks
}
func main() {}
Playground: https://play.golang.org/p/2JRgEyRA50
Two possibilities i can see. Firstly, in the first else if:
}else if arg[lenArg - 1] > arg[lenArg -2] {
If lenArg is 1 then lenArg-2will be -1. This means arg[lenArg-2] is arg[-1] which will give you out of bounds.
Secondly, in the second else if:
} else if arg[i] > arg[i+1] ... {
On the last iteration over the loop, i will be lenArg-1, if you add 1 to this you'll get arg[lenArg-1+1] or arg[lenArg] which will out of bounds. (The last available index is at lenArg-1)
The Go Programming Language Specification
Index expressions
A primary expression of the form
a[x]
denotes the element of the slice a indexed by x.
The index x must be of integer type or untyped; it is in range if
0 <= x < len(a)
Otherwise it is out of range.
You need to pay attention to corner cases like lengths 0, 1, and 2 for indices i - 1, i, i + 1 out of range. For example,
package main
// For array a, a[i] is a peak if it is not smaller than its neighbor(s),
// where a[-1] = a[n] = -∞.
func findPeaks(a []int) []int {
var p []int
// special cases
if len(a) == 0 {
return p
}
if len(a) == 1 {
return append(p, a[0])
}
// first
i := 0
if a[i] >= a[i+1] {
p = append(p, a[i])
}
// first < i < last
for i = 1; i < len(a)-1; i++ {
if a[i-1] <= a[i] && a[i] >= a[i+1] {
p = append(p, a[i])
}
}
// last
i = len(a) - 1
if a[i-1] <= a[i] {
p = append(p, a[i])
}
return p
}
func main() {}
Playground: https://play.golang.org/p/9klj1wYnXZ
The data I got are xlsx rows in this format: row 1 value 1 is the first cell (A1), row 1 value 2 is the second cell (B1) etc. Any cell can (but doesn't need to) contain styles e.g. Border, Fill etc. .Styles will be in curly brackets like in this data: [[["row 1 value 1",{"Border":null,"Fill":{"arrFill":{"BgColor":"red"}},"Font":null,"ApplyBorder":null}],"row 1 value 2","row 1 value 3"],["row 2 value 1","row 2 value 2","row 2 value 3"]]
How to unmarshal this data to get also the not neccessary style map?
Playground
You may need to use the reflect package to check data types in the resulting array/map. It looks tedious, but seems that is the only way out. I have pasted below some quick and dirt, but runnable code to illustrate the same:
package main
import (
"encoding/json"
"fmt"
"reflect"
)
func parsePrintArray(y interface{}) {
var dummy []interface{}
var dummy2 map[string]interface{}
if reflect.TypeOf(y) == reflect.TypeOf("") {
fmt.Printf("%s ", y)
return
}
if reflect.TypeOf(y) == reflect.TypeOf(dummy2) {
x := y.(map[string]interface{})
for ks, vi := range x {
fmt.Printf("\ndumping for key %s ", ks)
if vi != nil {
parsePrintArray(vi)
}
}
return
}
for k, yl := range y.([]interface{}) {
if reflect.TypeOf(yl) == reflect.TypeOf(dummy) {
fmt.Println("")
parsePrintArray(yl.([]interface{}))
} else if reflect.TypeOf(yl) == reflect.TypeOf("") {
fmt.Printf("%v: %s ", k, yl.(string))
} else if reflect.TypeOf(yl) == reflect.TypeOf(dummy2) {
x := yl.(map[string]interface{})
for ks, vi := range x {
fmt.Printf("\ndumping for key %s ", ks)
if vi != nil {
parsePrintArray(vi)
}
}
}
}
}
func main() {
x := "[[[\"row 1 value1\",{\"Border\":null,\"Fill\":{\"arrFill\":{\"BgColor\":\"red\"}},\"Font\":null,\"ApplyBorder\":null}],\"row 1 value2\",\"row 1 value 3\"],[\"row 2 value 1\",\"row 2 value 2\",\"row 2 value 3\"]]"
var y []interface{}
err := json.Unmarshal([]byte(x), &y)
if err != nil {
panic(err)
}
parsePrintArray(y)
fmt.Println("")
}