Skip to content

Commit

Permalink
Bitwise operators concept + exercises (concept)
Browse files Browse the repository at this point in the history
  • Loading branch information
leonideliseev committed Nov 11, 2024
1 parent 26635e1 commit af6fdec
Show file tree
Hide file tree
Showing 14 changed files with 715 additions and 0 deletions.
7 changes: 7 additions & 0 deletions concepts/bitwise-operators/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"blurb": "Bitwise operations can perform actions with numbers at the level of their bit representation.",
"authors": [
"leonideliseev"
],
"contributors": []
}
118 changes: 118 additions & 0 deletions concepts/bitwise-operators/about.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Introduction

`Bitwise operations` in Go are operations that apply to individual bits of a number, using the binary representation of numbers to produce a result.

They are most commonly used in cryptography, flag handling, and network programming.

## Binary Representation

To display a number in [binary format][binary-format-link], you can use the `fmt` package:

```go
a := 23
fmt.Printf("Number %d in binary: %b\n", a, a) // -> 10111
fmt.Printf("Number %d in 8-bit binary format: %08b\n", a, a) // -> 0001 0111
```

Understanding how decimal numbers are represented in binary is essential for using bitwise operators effectively.

~~~~exercism/advanced
Arithmetic operations in the base 2 number system - [binary arithmetic][binary-arithmetic-link].
How to convert a number with base 10 to a number with base 2 and back - [cpnversion][conversion-link].
~~~~

## Bitwise Operators

Bitwise operators perform operations on each bit of a number. Some operators are binary, used between two numbers (e.g., `a+b`), and others are unary, applied to a single number (e.g., `-a`).

__Binary Bitwise Operators__:

| Simbol | Name | Description |
|--------|------|-------------|
|& |AND |1 if both bits are 1|
|\| |OR |1 if at least one of the bits is 1|
|^ |XOR |1 if the bits differ|

_Examples_:

```go
a := 154 // 1001 1010
b := 83 // 0101 0011

and := a & b // 0001 0010 -> 18
or := a | b // 1101 1011 -> 219
xor := a ^ b // 1100 1001 -> 201
```

If you need to save the result back into the same variable, you can use the shortened form:

```go
a &= b // equivalent to a = a & b
```

~~~~exercism/note
Applying the XOR (`^`) operator to a number with itself always be 0:
```go
zero := a ^ a // always 0
```
~~~~

__Unary NOT Operator__:

| Simbol | Name | Description |
|--------|------|-------------|
|^ |NOT |Inverts the bits of a number|

_Example_:

```go
a := 154 // 1001 1010
not := ^a // 0110 0101 -> 101
```

__Shift Operations__:

| Simbol | Name | Description |
|--------|------|-------------|
|<<|Shift left |Shifts bits to the left by a specified number |
|>>|Shift right |Shifts bits to the right by a specified number|

_Examples_:

```go
a := 27 // 0001 1011
left := a << 2 // 0110 1100 -> 108 (two 0 was add)
right := a >> 2 // 0000 0110 -> 6 (two last bit was remove)
```

~~~~exercism/note
Each left shift is equivalent to multiplying by 2, and each right shift is equivalent to dividing by 2.
~~~~

## Usage example

To specify a number in binary format directly, you can use the prefix `0b`:

```go
var a uint8 = 0b0010_1101 // 45
```

Bitwise operations are often used when working with _masks_.
A [mask][mask-link] is a predefined number that can be used to modify incoming numbers.

_Example_: Let's say you need to extract the last 4 bits of a `uint16` number.
Here’s what the function might look like:

```go
LastFourBits(num uint16) uint16 {
var mask uint16 = 0b0000_0000_0000_1111
return mask & num
}
```

[binary-format-link]: https://en.wikipedia.org/wiki/Binary_number#Representation
[binary-arithmetic-link]: https://en.wikipedia.org/wiki/Binary_number#Binary_arithmetic
[conversion-link]: https://en.wikipedia.org/wiki/Binary_number#Conversion_to_and_from_other_numeral_systems
[mask-link]: https://en.wikipedia.org/wiki/Mask_(computing)
118 changes: 118 additions & 0 deletions concepts/bitwise-operators/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Introduction

`Bitwise operations` in Go are operations that apply to individual bits of a number, using the binary representation of numbers to produce a result.

They are most commonly used in cryptography, flag handling, and network programming.

## Binary Representation

To display a number in [binary format][binary-format-link], you can use the `fmt` package:

```go
a := 23
fmt.Printf("Number %d in binary: %b\n", a, a) // -> 10111
fmt.Printf("Number %d in 8-bit binary format: %08b\n", a, a) // -> 0001 0111
```

Understanding how decimal numbers are represented in binary is essential for using bitwise operators effectively.

~~~~exercism/advanced
Arithmetic operations in the base 2 number system - [binary arithmetic][binary-arithmetic-link].
How to convert a number with base 10 to a number with base 2 and back - [cpnversion][conversion-link].
~~~~

## Bitwise Operators

Bitwise operators perform operations on each bit of a number. Some operators are binary, used between two numbers (e.g., `a+b`), and others are unary, applied to a single number (e.g., `-a`).

__Binary Bitwise Operators__:

| Simbol | Name | Description |
|--------|------|-------------|
|& |AND |1 if both bits are 1|
|\| |OR |1 if at least one of the bits is 1|
|^ |XOR |1 if the bits differ|

_Examples_:

```go
a := 154 // 1001 1010
b := 83 // 0101 0011

and := a & b // 0001 0010 -> 18
or := a | b // 1101 1011 -> 219
xor := a ^ b // 1100 1001 -> 201
```

If you need to save the result back into the same variable, you can use the shortened form:

```go
a &= b // equivalent to a = a & b
```

~~~~exercism/note
Applying the XOR (`^`) operator to a number with itself always be 0:
```go
zero := a ^ a // always 0
```
~~~~

__Unary NOT Operator__:

| Simbol | Name | Description |
|--------|------|-------------|
|^ |NOT |Inverts the bits of a number|

_Example_:

```go
a := 154 // 1001 1010
not := ^a // 0110 0101 -> 101
```

__Shift Operations__:

| Simbol | Name | Description |
|--------|------|-------------|
|<<|Shift left |Shifts bits to the left by a specified number |
|>>|Shift right |Shifts bits to the right by a specified number|

_Examples_:

```go
a := 27 // 0001 1011
left := a << 2 // 0110 1100 -> 108 (two 0 was add)
right := a >> 2 // 0000 0110 -> 6 (two last bit was remove)
```

~~~~exercism/note
Each left shift is equivalent to multiplying by 2, and each right shift is equivalent to dividing by 2.
~~~~

## Usage example

To specify a number in binary format directly, you can use the prefix `0b`:

```go
var a uint8 = 0b0010_1101 // 45
```

Bitwise operations are often used when working with _masks_.
A [mask][mask-link] is a predefined number that can be used to modify incoming numbers.

_Example_: Let's say you need to extract the last 4 bits of a `uint16` number.
Here’s what the function might look like:

```go
LastFourBits(num uint16) uint16 {
var mask uint16 = 0b0000_0000_0000_1111
return mask & num
}
```

[binary-format-link]: https://en.wikipedia.org/wiki/Binary_number#Representation
[binary-arithmetic-link]: https://en.wikipedia.org/wiki/Binary_number#Binary_arithmetic
[conversion-link]: https://en.wikipedia.org/wiki/Binary_number#Conversion_to_and_from_other_numeral_systems
[mask-link]: https://en.wikipedia.org/wiki/Mask_(computing)
26 changes: 26 additions & 0 deletions concepts/bitwise-operators/links.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[
{
"url": "https://en.wikipedia.org/wiki/Binary_number#Representation",
"description": "About bit representations of numbers"
},
{
"url": "https://en.wikipedia.org/wiki/Binary_number#Conversion_to_and_from_other_numeral_systems",
"description": "Base conversion between numbers"
},
{
"url": "https://en.wikipedia.org/wiki/Binary_number#Binary_arithmetic",
"description": "Binary arithmetic"
},
{
"url": "https://en.wikipedia.org/wiki/Mask_(computing)",
"description": "Using bitwise operators: bitmask"
},
{
"url": "https://en.wikipedia.org/wiki/Hash_function",
"description": "Using bitwise operators: hash function"
},
{
"url": "https://stackoverflow.com/questions/28432398/difference-between-some-operators-golang",
"description": "Additional usage examples"
}
]
21 changes: 21 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,22 @@
},
"exercises": {
"concept": [
{
"name": "Sucurity Agent",
"slug": "security-agent",
"uuid": "61babb30-9d4c-4710-acac-93946715986c",
"concepts": [
"bitwise-operators"
],
"prerequisites": [
"arithmetic-operators",
"basics",
"numbers",
"range-iteration",
"type-conversion"
],
"status": "beta"
},
{
"name": "Gopher's Gorgeous Lasagna",
"slug": "lasagna",
Expand Down Expand Up @@ -2055,6 +2071,11 @@
"slug": "basics",
"uuid": "5d2b4677-1850-4ee4-890d-dc55a1654626"
},
{
"name": "Bitwise Operators",
"slug": "bitwise-operators",
"uuid": "6ae09ebc-9a9f-42f5-9f29-a5d1df7e28fc"
},
{
"name": "Booleans",
"slug": "booleans",
Expand Down
31 changes: 31 additions & 0 deletions exercises/concept/security-agent/.docs/hints.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Hints

## 1. Generate important number

- Remember that there’s an operation that can replace multiplication by 2
- Consider how `this` can help multiply a number by 2 several times in one step

## 2. Integrity Check

- Imagine that you have two identical numbers
- Think about using an operation that has a specific behavior with identical numbers
- If you start with `0` and apply this operation with number `a`, you get `a`: `0 _ a = a`
- Applying the operation again with the same number returns `0`:
`0 _ a _ a = 0`
- This operation doesn’t require a strict order of numbers — if the numbers are swapped, it still works
- `0 _ a _ b _ a = b`, `0 _ b _ a _ a _ b = 0`
- Apply this operation across [all elements][range-over-link] of the slice to determine if any number lacks a pair

## 3. Setting Flags

- Recall what you can use when you know which bits need to be changed
- If you need to set bits to `0`, consider an operation that always returns `0` regardless of the bit value in the other operand

## 4. Generate Key

- Start by performing the specified operation on `num`
- If you need to end up with a `uint32`, remember to [handle][type-conversions-link] that
- Place each bit in its _correct_ position

[range-over-link]: https://gobyexample.com/range-over-built-in-types
[type-conversions-link]: https://go.dev/tour/basics/13
Loading

0 comments on commit af6fdec

Please sign in to comment.