Tuesday, August 20, 2024

Java: of list and set

There are multiple ways to construct a list in java. (easier in python and other languages). To eliminate duplicates, you can use the stream distinct, or put it in a set (HashSet or LinkedHashSet to retain order) then make it back to a list.
	public static void main(String arg[]) {
		
		String a[] = new String[] { "A", "B", "C", "D", "A", "C", "E" };
        List<String> list = Arrays.asList(a);  // constructed one way
        List<String> list2 = List.of(a); // constructed another way (java 9+)
        List<String> list3 = List.of( "A", "B", "C", "D", "A", "C", "E" ); // yet another way 

        // using stream distinct one way
        List<String> noDups = list.stream().distinct().collect(Collectors.toList());
        // using stream distinct another way
        List<String> noDups2 = list2.stream().distinct().toList();
        
        // put on a set and make a iist out of it
        Set<String> set = new LinkedHashSet<>(); 
        set.addAll(list3); 
        List<String> noDups3 = new ArrayList<>(set);
        
        System.out.println(noDups);
        System.out.println(noDups2);
        System.out.println(noDups3);
	}

Wednesday, July 24, 2024

Python linear 2x2 system

This is a fun tool for any algebra 1 student. Solve a 2x2 linear system, and graph it.
import matplotlib.pyplot as plt
import numpy as np
import math

"""
Simple little 2x2 system example:
 x + 2y = 1
 3x + 5y = 2
 
 This can be written as matrix form [A][x] = [B]:
 
 [1 2][x] =  [1]
 [3 5][y]    [2]
"""
A = np.array([[1, 2], 
              [3, 5]])
B = np.array([1, 2])

XMIN, XMAX = -5, 5
YMIN, YMAX = -5, 5
GRIDSIZE = 1

STEPS = 101


a11 = A[0][0];
a12 = A[0][1];
a21 = A[1][0];
a22 = A[1][1];
b11 = B[0];
b12 = B[1];

def f(x):
    return (-a11*x+b11)/a12

def g(x):
    return (-a21*x+b12)/a22

x = np.linspace(XMIN,XMAX,STEPS)
plt.axis([XMIN,XMAX,YMIN,YMAX]) 

y1v = np.zeros(len(x))
y2v = np.zeros(len(x))
for i in range(len(x)):
    try: 
        y1v[i] = f(x[i])
        y2v[i] = g(x[i])
    except:
        pass

try:
    solution = np.linalg.solve(A, B)
    print("Solution")
    print(solution)
    solutionpoint =  "(${0:.2f}, ${1:.2f})".format(solution[0], solution[1]);
    plt.plot(solution[0],solution[1],'bo'); # blue circle
    plt.annotate( solutionpoint,(solution[0],solution[1]));
except:
    print("No solution")
    
eq1 = "{0}x+{1}y={2}".format(a11,a12,b11);
eq2 = "{0}x+{1}y={2}".format(a21,a22,b12);
plt.plot(x,y1v, color='r',label=eq1)
plt.plot(x,y2v, color='g',label=eq2)


# make axes
plt.axhline(y=0, color='k') # 'k' means black
plt.axvline(x=0, color='k')
# gca is get current axes 
plt.gca().set_aspect('equal')
plt.gca().set_xticks(np.arange(XMIN,XMAX,GRIDSIZE))
plt.gca().set_yticks(np.arange(YMIN,YMAX,GRIDSIZE))
plt.grid(True)
plt.legend() 
plt.show()


Monday, July 22, 2024

Python linear algebra

Every algebra 1 student should learn about solving a system of 2 equations and 2 unknowns. Then they will learn about 3 by 3... then gosh n by n. There is gotta be easier way to do this than combining equations, well yes there is, enter linear algebra. But solving a linear system of equation is still hard to do by hand, painful to punch it on your calculator too. Enter computer programming! Python can effortless do this with the Numpy library. Programming this from scratch is not a very pleasant programming task.
import numpy as np
 
"""
Simple little 2x2 system example:
 x + 2y = 1
 3x + 5y = 2
 
 This can be written as matrix form [A][x] = [B]:
 
 [1 2][x] =  [1]
 [3 5][y]    [2]
 
 
 So the solution is inv(A)B
 
 Inverse matrix is painful to do by hand, but numpy can do it easy,
 It even has a solve method
 """
 
A = np.array([[1, 2], 
              [3, 5]])
B = np.array([1, 2])

Ainv = np.linalg.inv(A)
solution = np.matmul(Ainv,B)
print("Solution by multiply inverse: ")
print(solution)

solution2 = np.linalg.solve(A, B)
print("Solution by linalg solve: ")
print(solution2)

Output:
Solution by multiply inverse matrix and right hand side: 
[-1.  1.]
or by linalg solve: 
[-1.  1.]
That means x=-1, y =1.

Wednesday, July 3, 2024

Python Simple Graphing (part 2)

With the little program from my previous post, I thought I could graph any function I passed to it? Let me try something a little more fancy like sin(x). I tried the following and got error
import matplotlib.pyplot as plt
import numpy as np
import math


def f(x):
    return math.sin(x)

# using 101 steps so I know I get to 0
x = np.linspace(-5,5,101)

plt.plot(x,f(x))
plt.show()
Error is "TypeError: only length-1 arrays can be converted to Python scalars". What??

Oh that's because this plt.plot() method really takes 2 arrays, the x values and the y values.

The following works better

import matplotlib.pyplot as plt
import numpy as np
import math


def f(x):
    return math.sin(x)

# using 101 steps so I know I get to 0
x = np.linspace(-5,5,101)

yv = np.zeros(len(x))
for i in range(len(x)):
    yv[i] = f(x[i])

plt.plot(x,yv)

plt.show()
This works a little better but I like axes and grids and properly scaled graph!

Ok after a little researching here we go:

import matplotlib.pyplot as plt
import numpy as np
import math

XMIN, XMAX = -5, 5
YMIN, YMAX = -5, 5
GRIDSIZE = 1

STEPS = 101


def f(x):
    return math.sin(x)


# using odd steps so I know I get to 0
x = np.linspace(XMIN,XMAX,STEPS)
plt.axis([XMIN,XMAX,YMIN,YMAX]) 

plt.title('my graph')

yv = np.zeros(len(x))
for i in range(len(x)):
    yv[i] = f(x[i])

plt.plot(x,yv)

# make axes
plt.axhline(y=0, color='k') # 'k' means black
plt.axvline(x=0, color='k')
# gca is get current axes 
plt.gca().set_aspect('equal')
plt.gca().set_xticks(np.arange(XMIN,XMAX,GRIDSIZE))
plt.gca().set_yticks(np.arange(YMIN,YMAX,GRIDSIZE))
plt.grid(True)

plt.show()

Monday, June 10, 2024

Python simple graphing

Pyplot lets you easily make a graph: https://matplotlib.org/stable/tutorials/pyplot.html. Lots of options here.

You first need to install it:.

pip3 install matplotlib

Here is some simple code. x range from -5,5. plot y=x2+1

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(-5,5,0.1)
y = x*x+1
plt.plot(x,y)
plt.show()
Although this works but it seems wacky scale.

And let me try some other function, let's give it tricky function y=1/x: Eeew this is ugly (and wrong)

This can be fixed if I change x to x = np.linspace(-5,5,100). See documentation here: https://numpy.org/doc/stable/reference/generated/numpy.linspace.html

But eew, it is not what I expect it to do at x=0? First do a step with odd number so you know 0 gets evaluated, then make your function a little method, and have an extra with statement to ignore bad output

import matplotlib.pyplot as plt
import numpy as np

def f(x):
    with np.errstate(divide='ignore', invalid='ignore'):
        return 1/x

# using 101 steps so I know I get to 0
x = np.linspace(-5,5,101)

plt.plot(x,f(x))
plt.show()

Ok a few lines give you much functionality... but less than super smooth if you ask me... There are many ways to supply that x range. and many ways to tweak graph like add axes, colors, labels, etc.