This is Ruby/Numo::NArray version of 100 numpy exercises (Repository)

1. Import the numpy package under the name np (★☆☆)

Python:

import numpy as np

Ruby:

In [2]:
require "numo/narray"
Out[2]:
true

2. Print the numpy version and the configuration (★☆☆)

Python:

print(np.__version__)
np.show_config()

Ruby:

In [2]:
p Numo::NArray::VERSION
"0.9.0.2"
Out[2]:
"0.9.0.2"

3. Create a null vector of size 10 (★☆☆)

Python:

Z = np.zeros(10)
print(Z)

Ruby:

In [3]:
z = Numo::DFloat.zeros(10)
p z
Numo::DFloat#shape=[10]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Out[3]:
Numo::DFloat#shape=[10]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

4. How to find the memory size of any array (★☆☆)

Python:

Z = np.zeros((10,10))
print("%d bytes" % (Z.size * Z.itemsize))

Ruby:

In [4]:
z = Numo::DFloat.zeros(10,10)
printf "%d bytes", z.byte_size
800 bytes

6. Create a null vector of size 10 but the fifth value which is 1 (★☆☆)

Python:

Z = np.zeros(10)
Z[4] = 1
print(Z)

Ruby:

In [2]:
z = Numo::DFloat.zeros(10)
z[4] = 1
p z
Numo::DFloat#shape=[10]
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0]
Out[2]:
Numo::DFloat#shape=[10]
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0]

7. Create a vector with values ranging from 10 to 49 (★☆☆)

Python:

Z = np.arange(10,50)
print(Z)

Ruby:

In [3]:
z = Numo::DFloat[10..49]
p z
Numo::DFloat#shape=[40]
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, ...]
Out[3]:
Numo::DFloat#shape=[40]
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, ...]

8. Reverse a vector (first element becomes last) (★☆☆)

Python:

Z = np.arange(50)
Z = Z[::-1]
print(Z)

Ruby:

In [4]:
z = Numo::Int32.new(50).seq
z = z.reverse
Out[4]:
Numo::Int32(view)#shape=[50]
[49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, ...]

9. Create a 3x3 matrix with values ranging from 0 to 8 (★☆☆)

Python:

Z = np.arange(9).reshape(3,3)
print(Z)

Ruby:

In [5]:
z = Numo::Int32.new(3,3).seq
p z
Numo::Int32#shape=[3,3]
[[0, 1, 2], 
 [3, 4, 5], 
 [6, 7, 8]]
Out[5]:
Numo::Int32#shape=[3,3]
[[0, 1, 2], 
 [3, 4, 5], 
 [6, 7, 8]]

10. Find indices of non-zero elements from [1,2,0,0,4,0] (★☆☆)

Python:

nz = np.nonzero([1,2,0,0,4,0])
print(nz)

Ruby:

In [6]:
nz = Numo::NArray[1,2,0,0,4,0].ne(0).where
p nz
Numo::Int32#shape=[3]
[0, 1, 4]
Out[6]:
Numo::Int32#shape=[3]
[0, 1, 4]

11. Create a 3x3 identity matrix (★☆☆)

Python:

Z = np.eye(3)
print(Z)

Ruby:

In [7]:
z = Numo::DFloat.eye(3)
p z
Numo::DFloat#shape=[3,3]
[[1, 0, 0], 
 [0, 1, 0], 
 [0, 0, 1]]
Out[7]:
Numo::DFloat#shape=[3,3]
[[1, 0, 0], 
 [0, 1, 0], 
 [0, 0, 1]]

12. Create a 3x3x3 array with random values (★☆☆)

Python:

Z = np.random.random((3,3,3))
print(Z)

Ruby:

In [8]:
z = Numo::DFloat.new(3,3,3).rand
p z
Numo::DFloat#shape=[3,3,3]
[[[0.0617545, 0.373067, 0.794815], 
  [0.201042, 0.116041, 0.344032], 
  [0.539948, 0.737815, 0.165089]], 
 [[0.0508827, 0.108065, 0.0687079], 
  [0.904121, 0.478644, 0.342969], 
  [0.164541, 0.74603, 0.138994]], 
 [[0.411576, 0.292532, 0.869421], 
  [0.0854984, 0.688965, 0.159977], 
  [0.279215, 0.625155, 0.676329]]]
Out[8]:
Numo::DFloat#shape=[3,3,3]
[[[0.0617545, 0.373067, 0.794815], 
  [0.201042, 0.116041, 0.344032], 
  [0.539948, 0.737815, 0.165089]], 
 [[0.0508827, 0.108065, 0.0687079], 
  [0.904121, 0.478644, 0.342969], 
  [0.164541, 0.74603, 0.138994]], 
 [[0.411576, 0.292532, 0.869421], 
  [0.0854984, 0.688965, 0.159977], 
  [0.279215, 0.625155, 0.676329]]]

13. Create a 10x10 array with random values and find the minimum and maximum values (★☆☆)

Python:

Z = np.random.random((10,10))
Zmin, Zmax = Z.min(), Z.max()
print(Zmin, Zmax)

Ruby:

In [10]:
z = Numo::DFloat.new(10,10).rand
zmin, zmax = z.minmax
p zmin, zmax
0.002701878465693965
0.995590771731077
Out[10]:
[0.002701878465693965, 0.995590771731077]

14. Create a random vector of size 30 and find the mean value (★☆☆)

Python:

Z = np.random.random(30)
m = Z.mean()
print(m)

Ruby:

In [3]:
z = Numo::DFloat.new(30).rand
m = z.mean
p m
0.35905260384501714
Out[3]:
0.35905260384501714

15. Create a 2d array with 1 on the border and 0 inside (★☆☆)

Python:

Z = np.ones((10,10))
Z[1:-1,1:-1] = 0
print(Z)

Ruby:

In [6]:
z = Numo::DFloat.ones(10,10)
z[1..-2,1..-2] = 0
p z
Numo::DFloat#shape=[10,10]
[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
Out[6]:
Numo::DFloat#shape=[10,10]
[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 1], 
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]

17. What is the result of the following expression? (★☆☆)

Python:

print(0 * np.nan)
print(np.nan == np.nan)
print(np.inf > np.nan)
print(np.nan - np.nan)
print(0.3 == 3 * 0.1)

Ruby:

In [7]:
0 * Float::NAN
Float::NAN == Float::NAN
Float::INFINITY > Float::NAN
Float::NAN - Float::NAN
0.3 == 3 * 0.1
Out[7]:
false

18. Create a 5x5 matrix with values 1,2,3,4 just below the diagonal (★☆☆)

Python:

Z = np.diag(1+np.arange(4),k=-1)
print(Z)

Ruby:

In [8]:
z = Numo::Int32.zeros(5,5)
z.diagonal(-1)[] = Numo::Int32[1..4]
p z
Numo::Int32#shape=[5,5]
[[0, 0, 0, 0, 0], 
 [1, 0, 0, 0, 0], 
 [0, 2, 0, 0, 0], 
 [0, 0, 3, 0, 0], 
 [0, 0, 0, 4, 0]]
Out[8]:
Numo::Int32#shape=[5,5]
[[0, 0, 0, 0, 0], 
 [1, 0, 0, 0, 0], 
 [0, 2, 0, 0, 0], 
 [0, 0, 3, 0, 0], 
 [0, 0, 0, 4, 0]]

19. Create a 8x8 matrix and fill it with a checkerboard pattern (★☆☆)

Python:

Z = np.zeros((8,8),dtype=int)
Z[1::2,::2] = 1
Z[::2,1::2] = 1
print(Z)

Ruby:

In [9]:
# todo: rangewithstep
x = Numo::Int32.new(1,8).seq
y = Numo::Int32.new(8,1).seq
z = (x+y)%2
p z
Numo::Int32#shape=[8,8]
[[0, 1, 0, 1, 0, 1, 0, 1], 
 [1, 0, 1, 0, 1, 0, 1, 0], 
 [0, 1, 0, 1, 0, 1, 0, 1], 
 [1, 0, 1, 0, 1, 0, 1, 0], 
 [0, 1, 0, 1, 0, 1, 0, 1], 
 [1, 0, 1, 0, 1, 0, 1, 0], 
 [0, 1, 0, 1, 0, 1, 0, 1], 
 [1, 0, 1, 0, 1, 0, 1, 0]]
Out[9]:
Numo::Int32#shape=[8,8]
[[0, 1, 0, 1, 0, 1, 0, 1], 
 [1, 0, 1, 0, 1, 0, 1, 0], 
 [0, 1, 0, 1, 0, 1, 0, 1], 
 [1, 0, 1, 0, 1, 0, 1, 0], 
 [0, 1, 0, 1, 0, 1, 0, 1], 
 [1, 0, 1, 0, 1, 0, 1, 0], 
 [0, 1, 0, 1, 0, 1, 0, 1], 
 [1, 0, 1, 0, 1, 0, 1, 0]]

20. Consider a (6,7,8) shape array, what is the index (x,y,z) of the 100th element?

Python:

print(np.unravel_index(100,(6,7,8)))

Ruby:

In [10]:
# NArray allows unraveled index access
z = Numo::Int32.new(6,7,8).seq
p z[100]
100
Out[10]:
100

22. Normalize a 5x5 random matrix (★☆☆)

Python:

Z = np.random.random((5,5))
Zmax, Zmin = Z.max(), Z.min()
Z = (Z - Zmin)/(Zmax - Zmin)
print(Z)

Ruby:

In [11]:
z = Numo::DFloat.new(5,5).rand
zmin, zmax = z.minmax
z = (z - zmin)/(zmax - zmin)
p z
Numo::DFloat#shape=[5,5]
[[0.403835, 0.315208, 1, 0.906438, 0.103955], 
 [0, 0.187591, 0.0340522, 0.950887, 0.52957], 
 [0.303649, 0.307339, 0.99628, 0.458339, 0.515865], 
 [0.525582, 0.876358, 0.0981913, 0.682091, 0.120115], 
 [0.715885, 0.215871, 0.941261, 0.187328, 0.393366]]
Out[11]:
Numo::DFloat#shape=[5,5]
[[0.403835, 0.315208, 1, 0.906438, 0.103955], 
 [0, 0.187591, 0.0340522, 0.950887, 0.52957], 
 [0.303649, 0.307339, 0.99628, 0.458339, 0.515865], 
 [0.525582, 0.876358, 0.0981913, 0.682091, 0.120115], 
 [0.715885, 0.215871, 0.941261, 0.187328, 0.393366]]

23. Create a custom dtype that describes a color as four unisgned bytes (RGBA) (★☆☆)

Python:

color = np.dtype([("r", np.ubyte, 1),
                  ("g", np.ubyte, 1),
                  ("b", np.ubyte, 1),
                  ("a", np.ubyte, 1)])

Ruby:

In [12]:
# todo: record
color = Numo::Struct.new do
  uint8 "r"
  uint8 "g"
  uint8 "b"
  uint8 "a"
end
Out[12]:
#<Class:0x000000017674c8>

24. Multiply a 5x3 matrix by a 3x2 matrix (real matrix product) (★☆☆)

Python:

Z = np.dot(np.ones((5,3)), np.ones((3,2)))
print(Z)

Ruby:

In [13]:
x = Numo::DFloat.ones(5,3)
y = Numo::DFloat.ones(3,2)
z = x.dot y
p z
Numo::DFloat#shape=[5,2]
[[3, 3], 
 [3, 3], 
 [3, 3], 
 [3, 3], 
 [3, 3]]
Out[13]:
Numo::DFloat#shape=[5,2]
[[3, 3], 
 [3, 3], 
 [3, 3], 
 [3, 3], 
 [3, 3]]

25. Given a 1D array, negate all elements which are between 3 and 8, in place. (★☆☆)

Python:

# Author: Evgeni Burovski

Z = np.arange(11)
Z[(3 < Z) & (Z <= 8)] *= -1
print(Z)

Ruby:

In [14]:
z = Numo::Int32.new(11).seq
z[(3 < z) & (z <= 8)] *= -1
Out[14]:
Numo::Int32#shape=[5]
[-4, -5, -6, -7, -8]

26. What is the output of the following script? (★☆☆)

Python:

# Author: Jake VanderPlas

print(sum(range(5),-1))
from numpy import *
print(sum(range(5),-1))

Ruby:

In [15]:
p [*0...5,-1].inject(:+)
p Numo::Int32[0...5].sum(-1)
9
10
Out[15]:
10

27. Consider an integer vector Z, which of these expressions are legal? (★☆☆)

Python:

Z = np.arange(5)
Z**Z
2 << Z >> 2
Z <- Z
1j*Z
Z/1/1
Z<Z>Z

Ruby:

In [16]:
z = Numo::Int32.new(5).seq
z**z
2 << z >> 2
z <- z
1i*z
z/1/1
z<z>z
TypeError: no implicit conversion of Numo::Int32 into Integer
(pry):51:in `<<'
(pry):51:in `<main>'
/var/lib/gems/2.1.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `eval'
/var/lib/gems/2.1.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `evaluate_ruby'
/var/lib/gems/2.1.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:323:in `handle_line'
/var/lib/gems/2.1.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:243:in `block (2 levels) in eval'
/var/lib/gems/2.1.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `catch'
/var/lib/gems/2.1.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `block in eval'
/var/lib/gems/2.1.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `catch'
/var/lib/gems/2.1.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `eval'
/var/lib/gems/2.1.0/gems/iruby-0.2.9/lib/iruby/backend.rb:65:in `eval'
/var/lib/gems/2.1.0/gems/iruby-0.2.9/lib/iruby/backend.rb:12:in `eval'
/var/lib/gems/2.1.0/gems/iruby-0.2.9/lib/iruby/kernel.rb:87:in `execute_request'
/var/lib/gems/2.1.0/gems/iruby-0.2.9/lib/iruby/kernel.rb:47:in `dispatch'
/var/lib/gems/2.1.0/gems/iruby-0.2.9/lib/iruby/kernel.rb:37:in `run'
/var/lib/gems/2.1.0/gems/iruby-0.2.9/lib/iruby/command.rb:70:in `run_kernel'
/var/lib/gems/2.1.0/gems/iruby-0.2.9/lib/iruby/command.rb:34:in `run'
/var/lib/gems/2.1.0/gems/iruby-0.2.9/bin/iruby:5:in `<top (required)>'
/usr/local/bin/iruby:22:in `load'
/usr/local/bin/iruby:22:in `<main>'

28. What are the result of the following expressions?

Python:

print(np.array(0) / np.array(0))
print(np.array(0) // np.array(0))
print(np.array([np.nan]).astype(int).astype(float))

Ruby:

In [17]:
p Numo::Int32[0] / Numo::Int32[0]
p Numo::DFloat[Float::NAN].cast_to(Numo::Int32).cast_to(Numo::DFloat)
ZeroDivisionError: error in NArray operation
(pry):56:in `/'
(pry):56:in `<main>'
/var/lib/gems/2.1.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `eval'
/var/lib/gems/2.1.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `evaluate_ruby'
/var/lib/gems/2.1.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:323:in `handle_line'
/var/lib/gems/2.1.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:243:in `block (2 levels) in eval'
/var/lib/gems/2.1.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `catch'
/var/lib/gems/2.1.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `block in eval'
/var/lib/gems/2.1.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `catch'
/var/lib/gems/2.1.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `eval'
/var/lib/gems/2.1.0/gems/iruby-0.2.9/lib/iruby/backend.rb:65:in `eval'
/var/lib/gems/2.1.0/gems/iruby-0.2.9/lib/iruby/backend.rb:12:in `eval'
/var/lib/gems/2.1.0/gems/iruby-0.2.9/lib/iruby/kernel.rb:87:in `execute_request'
/var/lib/gems/2.1.0/gems/iruby-0.2.9/lib/iruby/kernel.rb:47:in `dispatch'
/var/lib/gems/2.1.0/gems/iruby-0.2.9/lib/iruby/kernel.rb:37:in `run'
/var/lib/gems/2.1.0/gems/iruby-0.2.9/lib/iruby/command.rb:70:in `run_kernel'
/var/lib/gems/2.1.0/gems/iruby-0.2.9/lib/iruby/command.rb:34:in `run'
/var/lib/gems/2.1.0/gems/iruby-0.2.9/bin/iruby:5:in `<top (required)>'
/usr/local/bin/iruby:22:in `load'
/usr/local/bin/iruby:22:in `<main>'

29. How to round away from zero a float array ? (★☆☆)

Python:

# Author: Charles R Harris

Z = np.random.uniform(-10,+10,10)
print (np.trunc(Z + np.copysign(0.5, Z)))

Ruby:

In [18]:
z = Numo::DFloat.new(10).rand(-10,+10)
p (z + (0.5*z.sign)).trunc
# todo: copysign
Numo::DFloat#shape=[10]
[-7, -0, 10, -5, -7, -1, -10, -3, -1, -5]
Out[18]:
Numo::DFloat#shape=[10]
[-7, -0, 10, -5, -7, -1, -10, -3, -1, -5]

30. How to find common values between two arrays? (★☆☆)

Python:

Z1 = np.random.randint(0,10,10)
Z2 = np.random.randint(0,10,10)
print(np.intersect1d(Z1,Z2))

Ruby:

In [19]:
# todo: intersect1d
In [ ]: