goeg/src/chap4_ans/chap4_ans.go
2013-06-08 15:17:03 -07:00

152 lines
4.4 KiB
Go

// Copyright © 2011-12 Qtrac Ltd.
//
// This program or package and any associated files are licensed under the
// Apache License, Version 2.0 (the "License"); you may not use these files
// except in compliance with the License. You can get a copy of the License
// at: http://www.apache.org/licenses/LICENSE-2.0.
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"fmt"
"log"
"sort"
"strings"
)
func main() {
irregularMatrix := [][]int{{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11},
{12, 13, 14, 15},
{16, 17, 18, 19, 20}}
fmt.Println("irregular:", irregularMatrix)
slice := Flatten(irregularMatrix)
fmt.Printf("1x%d: %v\n", len(slice), slice)
fmt.Printf(" 3x%d: %v\n", neededRows(slice, 3), Make2D(slice, 3))
fmt.Printf(" 4x%d: %v\n", neededRows(slice, 4), Make2D(slice, 4))
fmt.Printf(" 5x%d: %v\n", neededRows(slice, 5), Make2D(slice, 5))
fmt.Printf(" 6x%d: %v\n", neededRows(slice, 6), Make2D(slice, 6))
slice = []int{9, 1, 9, 5, 4, 4, 2, 1, 5, 4, 8, 8, 4, 3, 6, 9, 5, 7, 5}
fmt.Println("Original:", slice)
slice = UniqueInts(slice)
fmt.Println("Unique: ", slice)
iniData := []string{
"; Cut down copy of Mozilla application.ini file",
"",
"[App]",
"Vendor=Mozilla",
"Name=Iceweasel",
"Profile=mozilla/firefox",
"Version=3.5.16",
"[Gecko]",
"MinVersion=1.9.1",
"MaxVersion=1.9.1.*",
"[XRE]",
"EnableProfileMigrator=0",
"EnableExtensionManager=1",
}
ini := ParseIni(iniData)
PrintIni(ini)
}
// Minimum result length is len(matrix) + len(matrix[0]); by using append()
// we can cope with irregular matrices whose inner slices are of different
// lengths.
func Flatten(matrix [][]int) []int {
slice := make([]int, 0, len(matrix)+len(matrix[0]))
for _, innerSlice := range matrix {
for _, x := range innerSlice {
slice = append(slice, x)
}
}
return slice
}
func Make2D(slice []int, columns int) [][]int {
matrix := make([][]int, neededRows(slice, columns))
for i, x := range slice {
row := i / columns
column := i % columns
if matrix[row] == nil {
matrix[row] = make([]int, columns)
}
matrix[row][column] = x
}
return matrix
}
func neededRows(slice []int, columns int) int {
rows := len(slice) / columns
if len(slice)%columns != 0 {
rows++
}
return rows
}
func UniqueInts(slice []int) []int {
seen := map[int]bool{} // == make(map[int]bool)
unique := []int{} // == make([]int, 0)
for _, x := range slice {
if _, found := seen[x]; !found {
unique = append(unique, x)
seen[x] = true
}
}
return unique
}
func ParseIni(lines []string) map[string]map[string]string {
const separator = "="
ini := make(map[string]map[string]string)
group := "General"
for _, line := range lines {
line := strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, ";") {
continue
}
if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
group = line[1 : len(line)-1]
} else if i := strings.Index(line, separator); i > -1 {
key := line[:i]
value := line[i+len(separator):]
if _, found := ini[group]; !found {
ini[group] = make(map[string]string)
}
ini[group][key] = value
} else {
log.Print("failed to parse line:", line)
}
}
return ini
}
func PrintIni(ini map[string]map[string]string) {
groups := make([]string, 0, len(ini))
for group := range ini {
groups = append(groups, group)
}
sort.Strings(groups)
for i, group := range groups {
fmt.Printf("[%s]\n", group)
keys := make([]string, 0, len(ini[group]))
for key := range ini[group] {
keys = append(keys, key)
}
sort.Strings(keys)
for _, key := range keys {
fmt.Printf("%s=%s\n", key, ini[group][key])
}
if i+1 < len(groups) {
fmt.Println()
}
}
}