题图来自 Rust vs Go 2023^[1]^
81. Round floating point number to integer
Declare integer y and initialize it with the rounded value of floating point number x . Ties (when the fractional part of x is exactly .5) must be rounded up (to positive infinity).
按规则取整
package main
import (
"fmt"
"math"
)
func round(x float64) int {
y := int(math.Floor(x + 0.5))
return y
}
func main() {
for _, x := range []float64{-1.1, -0.9, -0.5, -0.1, 0., 0.1, 0.5, 0.9, 1.1} {
fmt.Printf("%5.1f %5d\n", x, round(x))
}
}
-1.1 -1
-0.9 -1
-0.5 0
-0.1 0
0.0 0
0.1 0
0.5 1
0.9 1
1.1 1
fn main() {
let x : f64 = 2.71828;
let y = x.round() as i64;
println!("{} {}", x, y);
}
2.71828 3
82. Count substring occurrences
统计子字符串出现次数
package main
import (
"fmt"
"strings"
)
func main() {
s := "Romaromamam"
t := "mam"
x := strings.Count(s, t)
fmt.Println(x)
}
1
fn main() {
let s = "lorem ipsum lorem ipsum lorem ipsum lorem ipsum";
let t = "ipsum";
let c = s.matches(t).count();
println!("{} occurrences", c);
}
Disjoint matches: overlapping occurrences are not counted.
4 occurrences
83. Regex with character repetition
Declare regular expression r matching strings "http", "htttp", "httttp", etc.
正则表达式匹配重复字符
package main
import (
"fmt"
"regexp"
)
func main() {
r := regexp.MustCompile("htt+p")
for _, s := range []string{
"hp",
"htp",
"http",
"htttp",
"httttp",
"htttttp",
"htttttp",
"word htttp in a sentence",
} {
fmt.Println(s, "=>", r.MatchString(s))
}
}
hp => false
htp => false
http => true
htttp => true
httttp => true
htttttp => true
htttttp => true
word htttp in a sentence => true
extern crate regex;
use regex::Regex;
fn main() {
let r = Regex::new(r"htt+p").unwrap();
assert!(r.is_match("http"));
assert!(r.is_match("htttp"));
assert!(r.is_match("httttp"));
}
84. Count bits set in integer binary representation
Count number c of 1s in the integer i in base 2.
E.g. i=6 → c=2
计算十进制整型的二进制表示中 1的个数
package main
import "fmt"
func PopCountUInt64(i uint64) (c int) {
// bit population count, see
// http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
i -= (i >> 1) & 0x5555555555555555
i = (i>>2)&0x3333333333333333 + i&0x3333333333333333
i += i >> 4
i &= 0x0f0f0f0f0f0f0f0f
i *= 0x0101010101010101
return int(i >> 56)
}
func PopCountUInt32(i uint32) (n int) {
// bit population count, see
// http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
i -= (i >> 1) & 0x55555555
i = (i>>2)&0x33333333 + i&0x33333333
i += i >> 4
i &= 0x0f0f0f0f
i *= 0x01010101
return int(i >> 24)
}
func main() {
for i := uint64(0); i < 16; i++ {
c := PopCountUInt64(i)
fmt.Printf("%4d %04[1]b %d\n", i, c)
}
for i := uint32(0); i < 16; i++ {
c := PopCountUInt32(i)
fmt.Printf("%4d %04[1]b %d\n", i, c)
}
}
0 0000 0
1 0001 1
2 0010 1
3 0011 2
4 0100 1
5 0101 2
6 0110 2
7 0111 3
8 1000 1
9 1001 2
10 1010 2
11 1011 3
12 1100 2
13 1101 3
14 1110 3
15 1111 4
0 0000 0
1 0001 1
2 0010 1
3 0011 2
4 0100 1
5 0101 2
6 0110 2
7 0111 3
8 1000 1
9 1001 2
10 1010 2
11 1011 3
12 1100 2
13 1101 3
14 1110 3
15 1111 4
This was useful only before go 1.9. See math/bits.OnesCount instead
or
package main
import (
"fmt"
"math/bits"
)
func main() {
for i := uint(0); i < 16; i++ {
c := bits.OnesCount(i)
fmt.Printf("%4d %04[1]b %d\n", i, c)
}
}
0 0000 0
1 0001 1
2 0010 1
3 0011 2
4 0100 1
5 0101 2
6 0110 2
7 0111 3
8 1000 1
9 1001 2
10 1010 2
11 1011 3
12 1100 2
13 1101 3
14 1110 3
15 1111 4
fn main() {
println!("{}", 6usize.count_ones())
}
2
85. Check if integer addition will overflow
检查两个整型相加是否溢出
package main
import (
"fmt"
"math"
)
func willAddOverflow(a, b int64) bool {
return a > math.MaxInt64-b
}
func main() {
fmt.Println(willAddOverflow(11111111111111111, 2))
}
false
fn adding_will_overflow(x: usize, y: usize) -> bool {
x.checked_add(y).is_none()
}
fn main() {
{
let (x, y) = (2345678, 9012345);
let overflow = adding_will_overflow(x, y);
println!(
"{} + {} {}",
x,
y,
if overflow {
"overflows"
} else {
"doesn't overflow"
}
);
}
{
let (x, y) = (2345678901, 9012345678);
let overflow = adding_will_overflow(x, y);
println!(
"{} + {} {}",
x,
y,
if overflow {
"overflows"
} else {
"doesn't overflow"
}
);
}
{
let (x, y) = (2345678901234, 9012345678901);
let overflow = adding_will_overflow(x, y);
println!(
"{} + {} {}",
x,
y,
if overflow {
"overflows"
} else {
"doesn't overflow"
}
);
}
{
let (x, y) = (23456789012345678, 90123456789012345);
let overflow = adding_will_overflow(x, y);
println!(
"{} + {} {}",
x,
y,
if overflow {
"overflows"
} else {
"doesn't overflow"
}
);
}
{
let (x, y) = (12345678901234567890, 9012345678901234567);
let overflow = adding_will_overflow(x, y);
println!(
"{} + {} {}",
x,
y,
if overflow {
"overflows"
} else {
"doesn't overflow"
}
);
}
}
2345678 + 9012345 doesn't overflow
2345678901 + 9012345678 doesn't overflow
2345678901234 + 9012345678901 doesn't overflow
23456789012345678 + 90123456789012345 doesn't overflow
12345678901234567890 + 9012345678901234567 overflows
86. Check if integer multiplication will overflow
检查整型相乘是否溢出
package main
import (
"fmt"
)
func multiplyWillOverflow(x, y uint64) bool {
if x <= 1 || y <= 1 {
return false
}
d := x * y
return d/y != x
}
func main() {
{
var x, y uint64 = 2345, 6789
if multiplyWillOverflow(x, y) {
fmt.Println(x, "*", y, "overflows")
} else {
fmt.Println(x, "*", y, "doesn't overflow")
}
}
{
var x, y uint64 = 2345678, 9012345
if multiplyWillOverflow(x, y) {
fmt.Println(x, "*", y, "overflows")
} else {
fmt.Println(x, "*", y, "doesn't overflow")
}
}
{
var x, y uint64 = 2345678901, 9012345678
if multiplyWillOverflow(x, y) {
fmt.Println(x, "*", y, "overflows")
} else {
fmt.Println(x, "*", y, "doesn't overflow")
}
}
}
2345 * 6789 doesn't overflow
2345678 * 9012345 doesn't overflow
2345678901 * 9012345678 overflows
fn main() {
{
let (x, y) = (2345, 6789);
let overflow = multiply_will_overflow(x, y);
println!(
"{} * {} {}",
x,
y,
if overflow {
"overflows"
} else {
"doesn't overflow"
}
);
}
{
let (x, y) = (2345678, 9012345);
let overflow = multiply_will_overflow(x, y);
println!(
"{} * {} {}",
x,
y,
if overflow {
"overflows"
} else {
"doesn't overflow"
}
);
}
{
let (x, y) = (2345678901, 9012345678);
let overflow = multiply_will_overflow(x, y);
println!(
"{} * {} {}",
x,
y,
if overflow {
"overflows"
} else {
"doesn't overflow"
}
);
}
}
fn multiply_will_overflow(x: i64, y: i64) -> bool {
x.checked_mul(y).is_none()
}
2345 * 6789 doesn't overflow
2345678 * 9012345 doesn't overflow
2345678901 * 9012345678 overflows
87. Stop program
Exit immediately.
If some extra cleanup work is executed by the program runtime (not by the OS itself), describe it.
停止程序,立即退出。
package main
import "os"
func main() {
os.Exit(1)
print(2222)
}
fn main() {
std::process::exit(1);
println!("42");
}
88. Allocate 1M bytes
分配1M内存
package main
import "fmt"
func main() {
buf := make([]byte, 1000000)
for i, b := range buf {
if b != 0 {
fmt.Println("Found unexpected value", b, "at position", i)
}
}
fmt.Println("Buffer was correctly initialized with zero values.")
}
Buffer was correctly initialized with zero values.
fn main() {
let buf: Vec<u8> = Vec::with_capacity(1024 * 1024);
println!("{:?}", buf.capacity());
}
1048576
89. Handle invalid argument
处理无效参数
package main
import "fmt"
// NewSquareMatrix creates a N-by-N matrix
func NewSquareMatrix(N int) ([][]float64, error) {
if N < 0 {
return nil, fmt.Errorf("Invalid size %d: order cannot be negative", N)
}
matrix := make([][]float64, N)
for i := range matrix {
matrix[i] = make([]float64, N)
}
return matrix, nil
}
func main() {
N1 := 3
matrix1, err1 := NewSquareMatrix(N1)
if err1 == nil {
fmt.Println(matrix1)
} else {
fmt.Println(err1)
}
N2 := -2
matrix2, err2 := NewSquareMatrix(N2)
if err2 == nil {
fmt.Println(matrix2)
} else {
fmt.Println(err2)
}
}
[[0 0 0] [0 0 0] [0 0 0]]
Invalid size -2: order cannot be negative
#[derive(Debug, PartialEq, Eq)]
enum CustomError { InvalidAnswer }
fn do_stuff(x: i32) -> Result<i32, CustomError> {
if x != 42 {
%2
90. Read-only outside
外部只读
type Foo struct {
x int
}
func (f *Foo) X() int {
return f.x
}
x is private, because it is not capitalized.
(*Foo).X is a public getter (a read accessor).
struct Foo {
x: usize
}
impl Foo {
pub fn new(x: usize) -> Self {
Foo { x }
}
pub fn x<'a>(&'a self) -> &'a usize {
&self.x
}
}
91. Load JSON file into struct
json转结构体
package main
import "fmt"
import "io/ioutil"
import "encoding/json"
func readJSONFile() error {
var x Person
buffer, err := ioutil.ReadFile(filename)
if err != nil {
return err
}
err = json.Unmarshal(buffer, &x)
if err != nil {
return err
}
fmt.Println(x)
return nil
}
func main() {
err := readJSONFile()
if err != nil {
panic(err)
}
}
type Person struct {
FirstName string
Age int
}
const filename = "/tmp/data.json"
func init() {
err := ioutil.WriteFile(filename, []byte(`
{
"FirstName":"Napoléon",
"Age": 51
}`), 0644)
if err != nil {
panic(err)
}
}
{Napoléon 51}
or
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
)
func readJSONFile() error {
var x Person
r, err := os.Open(filename)
if err != nil {
return err
}
decoder := json.NewDecoder(r)
err = decoder.Decode(&x)
if err != nil {
return err
}
fmt.Println(x)
return nil
}
func main() {
err := readJSONFile()
if err != nil {
panic(err)
}
}
type Person struct {
FirstName string
Age int
}
const filename = "/tmp/data.json"
func init() {
err := ioutil.WriteFile(filename, []byte(`
{
"FirstName":"Napoléon",
"Age": 51
}`), 0644)
if err != nil {
panic(err)
}
}
{Napoléon 51}
#[macro_use] extern crate serde_derive;
extern crate serde_json;
use std::fs::File;
let x = ::serde_json::from_reader(File::open("data.json")?)?;
92. Save object into JSON file
将json对象写入文件
package main
import "fmt"
import "io/ioutil"
import "encoding/json"
func writeJSONFile() error {
x := Person{
FirstName: "Napoléon",
Age: 51,
}
buffer, err := json.MarshalIndent(x, "", " ")
if err != nil {
return err
}
return ioutil.WriteFile(filename, buffer, 0644)
}
func main() {
err := writeJSONFile()
if err != nil {
panic(err)
}
fmt.Println("Done.")
}
type Person struct {
FirstName string
Age int
}
const filename = "/tmp/data.json"
json.MarshalIndent is more human-readable than json.Marshal.
Done.
extern crate serde_json;
#[macro_use] extern crate serde_derive;
use std::fs::File;
::serde_json::to_writer(&File::create("data.json")?, &x)?
93. Pass a runnable procedure as parameter
Implement procedure control which receives one parameter f, and runs f.
以函数作为参数
package main
import "fmt"
func main() {
control(greet)
}
func control(f func()) {
fmt.Println("Before f")
f()
fmt.Println("After f")
}
func greet() {
fmt.Println("Hello, developers")
}
Go supports first class functions, higher-order functions, user-defined function types, function literals, and closures.
Before f
Hello, developers
After f
fn control(f: impl Fn()) {
f();
}
fn hello() {
println!("Hello,");
}
fn main() {
control(hello);
control(|| { println!("Is there anybody in there?"); });
}
Hello,
Is there anybody in there?
94. Print type of variable
打印变量的类型
package main
import (
"fmt"
"os"
"reflect"
)
func main() {
var x interface{}
x = "Hello"
fmt.Println(reflect.TypeOf(x))
x = 4
fmt.Println(reflect.TypeOf(x))
x = os.NewFile(0777, "foobar.txt")
fmt.Println(reflect.TypeOf(x))
}
string
int
*os.File
or
package main
import (
"fmt"
"os"
)
func main() {
var x interface{}
x = "Hello"
fmt.Printf("%T", x)
fmt.Println()
x = 4
fmt.Printf("%T", x)
fmt.Println()
x = os.NewFile(0777, "foobar.txt")
fmt.Printf("%T", x)
fmt.Println()
}
string
int
*os.File
#![feature(core_intrinsics)]
fn type_of<T>(_: &T) -> String {
format!("{}", std::intrinsics::type_name::<T>())
}
fn main() {
let x: i32 = 1;
println!("{}", type_of(&x));
}
i32
95. Get file size
获取文件的大小
package main
import (
"fmt"
"io/ioutil"
"os"
)
func main() {
err := printSize("file.txt")
if err != nil {
panic(err)
}
}
func printSize(path string) error {
info, err := os.Stat(path)
if err != nil {
return err
}
x := info.Size()
fmt.Println(x)
return nil
}
func init() {
// The file will only contains the characters "Hello", no newlines.
buffer := []byte("Hello")
err := ioutil.WriteFile("file.txt", buffer, 0644)
if err != nil {
panic(err)
}
}
5
use std::fs;
fn filesize(path: &str) -> Result<u64, std::io::Error> {
let x = fs::metadata(path)?.len();
Ok(x)
}
fn main() {
let path = "/etc/hosts";
let x = filesize(path);
println!("{}: {:?} bytes", path, x.unwrap());
}
/etc/hosts: 150 bytes
or
use std::path::Path;
fn filesize(path: &std::path::Path) -> Result<u64, std::io::Error> {
let x = path.metadata()?.len();
Ok(x)
}
fn main() {
let path = Path::new("/etc/hosts");
let x = filesize(path);
println!("{:?}: {:?} bytes", path, x.unwrap());
}
"/etc/hosts": 150 bytes
96. Check string prefix
Set boolean b to true if string s starts with prefix prefix, false otherwise.
检查两个字符串前缀是否一致
package main
import (
"fmt"
"strings"
)
func check(s, prefix string) {
b := strings.HasPrefix(s, prefix)
if b {
fmt.Println(s, "starts with", prefix)
} else {
fmt.Println(s, "doesn't start with", prefix)
}
}
func main() {
check("bar", "foo")
check("foobar", "foo")
}
bar doesn't start with foo
foobar starts with foo
fn main() {
let s = "bananas";
let prefix = "bana";
let b = s.starts_with(prefix);
println!("{:?}", b);
}
true
97. Check string suffix
Set boolean b to true if string s ends with string suffix, false otherwise.
检查字符串后缀
package main
import (
"fmt"
"strings"
)
func check(s, suffix string) {
b := strings.HasSuffix(s, suffix)
if b {
fmt.Println(s, "ends with", suffix)
} else {
fmt.Println(s, "doesn't end with", suffix)
}
}
func main() {
check("foo", "bar")
check("foobar", "bar")
}
foo doesn't end with bar
foobar ends with bar
fn main() {
let s = "bananas";
let suffix = "nas";
let b = s.ends_with(suffix);
println!("{:?}", b);
}
true
98. Epoch seconds to date object
Convert a timestamp ts (number of seconds in epoch-time) to a date with time d. E.g. 0 -> 1970-01-01 00:00:00
时间戳转日期
package main
import (
"fmt"
"time"
)
func main() {
ts := int64(1451606400)
d := time.Unix(ts, 0)
fmt.Println(d)
}
2016-01-01 00:00:00 +0000 UTC
extern crate chrono;
use chrono::prelude::*;
fn main() {
let ts = 1451606400;
let d = NaiveDateTime::from_timestamp(ts, 0);
println!("{}", d);
}
2016-01-01 00:00:00
99. Format date YYYY-MM-DD
Assign to string x the value of fields (year, month, day) of date d, in format YYYY-MM-DD.
时间格式转换
package main
import (
"fmt"
"time"
)
func main() {
d := time.Now()
x := d.Format("2006-01-02")
fmt.Println(x)
// The output may be "2009-11-10" because the Playground's clock is fixed in the past.
}
2009-11-10
extern crate chrono;
use chrono::prelude::*;
fn main() {
println!("{}", Utc::today().format("%Y-%m-%d"))
}
2021-07-17
100. Sort by a comparator
Sort elements of array-like collection items, using a comparator c.
根据某个字段排序
package main
import "fmt"
import "sort"
type Item struct {
label string
p int
lang string
}
// c returns true if x is "inferior to" y (in a custom way)
func c(x, y Item) bool {
return x.p < y.p
}
type ItemCSorter []Item
func (s ItemCSorter) Len() int { return len(s) }
func (s ItemCSorter) Less(i, j int) bool { return c(s[i], s[j]) }
func (s ItemCSorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func sortItems(items []Item) {
sorter := ItemCSorter(items)
sort.Sort(sorter)
}
func main() {
items := []Item{
{"twelve", 12, "english"},
{"six", 6, "english"},
{"eleven", 11, "english"},
{"zero", 0, "english"},
{"two", 2, "english"},
}
fmt.Println("Unsorted: ", items)
sortItems(items)
fmt.Println("Sorted: ", items)
}
c has type func(Item, Item) bool.
Unsorted: [{twelve 12 english} {six 6 english} {eleven 11 english} {zero 0 english} {two 2 english}]
Sorted: [{zero 0 english} {two 2 english} {six 6 english} {eleven 11 english} {twelve 12 english}]
or
package main
import "fmt"
import "sort"
type Item struct {
label string
p int
lang string
}
type ItemsSorter struct {
items []Item
c func(x, y Item) bool
}
func (s ItemsSorter) Len() int { return len(s.items) }
func (s ItemsSorter) Less(i, j int) bool { return s.c(s.items[i], s.items[j]) }
func (s ItemsSorter) Swap(i, j int) { s.items[i], s.items[j] = s.items[j], s.items[i] }
func sortItems(items []Item, c func(x, y Item) bool) {
sorter := ItemsSorter{
items,
c,
}
sort.Sort(sorter)
}
func main() {
items := []Item{
{"twelve", 12, "english"},
{"six", 6, "english"},
{"eleven", 11, "english"},
{"zero", 0, "english"},
{"two", 2, "english"},
}
fmt.Println("Unsorted: ", items)
c := func(x, y Item) bool {
return x.p < y.p
}
sortItems(items, c)
fmt.Println("Sorted: ", items)
}
ItemsSorter contains c, which can be any comparator decided at runtime.
Unsorted: [{twelve 12 english} {six 6 english} {eleven 11 english} {zero 0 english} {two 2 english}]
Sorted: [{zero 0 english} {two 2 english} {six 6 english} {eleven 11 english} {twelve 12 english}]
or
package main
import "fmt"
import "sort"
type Item struct {
label string
p int
lang string
}
// c returns true if x is "inferior to" y (in a custom way)
func c(x, y Item) bool {
return x.p < y.p
}
func main() {
items := []Item{
{"twelve", 12, "english"},
{"six", 6, "english"},
{"eleven", 11, "english"},
{"zero", 0, "english"},
{"two", 2, "english"},
}
fmt.Println("Unsorted: ", items)
sort.Slice(items, func(i, j int) bool {
return c(items[i], items[j])
})
fmt.Println("Sorted: ", items)
}
Since Go 1.8, a single func parameter is sufficient to sort a slice.
Unsorted: [{twelve 12 english} {six 6 english} {eleven 11 english} {zero 0 english} {two 2 english}]
Sorted: [{zero 0 english} {two 2 english} {six 6 english} {eleven 11 english} {twelve 12 english}]
fn main() {
let mut items = [1, 7, 5, 2, 3];
items.sort_by(i32::cmp);
println!("{:?}", items);
}
[1, 2, 3, 5, 7]
参考资料
[1]
Rust vs Go 2023: https://arkiana.com/rust-vs-go/
本文由mdnice多平台发布