Python dictionary key error '0' but 0 is in dictionary [duplicate] - python

This question already has an answer here:
Key error '0' with dict format
(1 answer)
Closed 3 years ago.
In the graph class, I had made a vertList dictionary which stores vertex name and vertex class object, the dictionary which throws key error 0 in relax function when calling in Dijkstra function.
I had tried using get function instead of direct calling from the dictionary itself.
from collections import defaultdict
import math
import heapq
class PriorityQueue:
def __init__(self):
self.is_empty = True
self.length = 0
self.pqueue = []
def makePQueue(self, l):
self.pqueue = l.copy()
heapq.heapify(self.pqueue)
if(len(l) > 0):
self.length = len(l)
self.is_empty = False
def addElement(self, element):
heapq.heappush(self.pqueue, element)
self.length = self.length+1
def removeElement(self):
if(self.length > 0):
element = heapq.heappop(self.pqueue)
self.length = self.length-1
if(self.length == 0):
self.is_empty = True
return element
else:
return None
# vertex class
class Vertex:
def __init__(self, key):
self.id = key
self.parent = None
self.distFromSource = math.inf
def getId(self):
return self.id
def getParent(self):
return self.parent
def addParent(self, p):
self.parent = p
def getDistSource(self):
return self.distFromSource
def setDistFromSource(self, d):
self.distFromSource = d
# Graph class
class Graph:
def __init__(self):
self.graph = defaultdict(list)
self.soruce = None
self.vertList = {}
def addVertex(self, v):
if(v not in list(self.vertList.keys())):
ver = Vertex(v)
self.vertList[v] = ver
def addEdge(self, u, v, c):
if(u not in list(self.vertList.keys())):
ver = Vertex(u)
self.vertList[u] = ver
if(v not in list(self.vertList.keys())):
ver = Vertex(v)
self.vertList[v] = ver
self.graph[u].append((v, c))
def getWeight(self, u, v):
# binary search can be implemented for speed
for i in self.graph[u]:
if(i[0] == v):
return i[1]
def setSource(self, s):
if(s not in list(self.vertList.keys())):
ver = Vertex(s)
self.vertList[s] = ver
self.vertList[s].setDistFromSource(0)
self.source = self.vertList[s]
self.source.setDistFromSource(0)
def getSource(self):
return self.source.getId()
def getDistList(self):
l = [(self.vertList[i].getDistSource(), str(i))
for i in list(self.vertList.keys())]
return l
# def costArray(self):
# l = [i.]
# implementation of edge array of cost
def relax(self, u, v, c):
if(self.vertList[v].getDistSource() > self.vertList[u].getDistSource()+c):
self.vertList[v].setDistFromSource(
self.vertList[u].getDistSource()+c)
self.vertList[v].addParent(self.vertList[u])
def dijkstra(graph):
ss = []
l = graph.getDistList()
pq = PriorityQueue()
pq.makePQueue(l)
# print(pq.pqueue)
while(pq.is_empty == False):
(cost, u) = pq.removeElement()
# in priority queue on the basis of cost
if int(u) not in ss:
ss = ss.append(int(u))
for (i, c) in graph.graph[int(u)]:
graph.relax(u, i, c)
```
g = Graph()
g.addEdge(0, 1, 3)
g.addEdge(0, 2, 2)
g.addEdge(0, 3, 5)
g.addEdge(1, 0, 3)
g.addEdge(1, 4, 3)
g.addEdge(4, 1, 3)
g.addEdge(4, 2, 1)
g.addEdge(4, 6, 4)
g.addEdge(2, 0, 2)
g.addEdge(2, 4, 1)
g.addEdge(2, 5, 6)
g.addEdge(3, 0, 5)
g.addEdge(3, 5, 2)
g.addEdge(5, 2, 6)
g.addEdge(5, 3, 2)
g.addEdge(5, 6, 1)
g.addEdge(5, 7, 4)
g.addEdge(6, 4, 4)
g.addEdge(6, 5, 1)
g.addEdge(6, 7, 2)
g.addEdge(7, 5, 4)
g.addEdge(7, 6, 2)
g.setSource(0)
dijkstra(g)
Exception
python graph.py
Traceback (most recent call last):
File "graph.py", line 155, in <module>
dijkstra(g)
File "graph.py", line 126, in dijkstra
graph.relax(u, i, c)
File "graph.py", line 108, in relax
if(self.vertList[v].getDistSource() >
self.vertList[u].getDistSource()+c):
KeyError: '0'

When you call your relax() method, u is a string, not an integer!
That's whhy you get a KeyError: there is indeed a 0 key, but not '0'.
When you defined the priority queue, you explicitly store strings:
def getDistList(self):
l = [(self.vertList[i].getDistSource(), str(i))
for i in list(self.vertList.keys())]
return l
Then, in your dijkstra method, you convert this string to an int in your if statement, but not in the graph.relax() call after that:
if int(u) not in ss:
ss = ss.append(int(u))
for (i, c) in graph.graph[int(u)]:
graph.relax(u, i, c)

Related

Python: Heapify a list of tuples (Dijkstra's Algo)

Here is my code for Dijkstra's Algorithm.
I have declared a "Vertex" class and a "Graph" class.
I am using heapq module and heapifying the list "unvisitedQueue" of tuples. But even then an error shows up saying " TypeError: '<' not supported between instances of 'Vertex' and 'Vertex' " even when "v.getDistance()" returns either 0 or float('inf').
import heapq
class Vertex:
def __init__(self, node):
self.id = node
self.adjacent = {}
self.previous = None
self.distance = float('inf')
def addNeighbor(self, neighbor, weight = 0):
self.adjacent[neighbor] = weight
def getConnections(self):
return self.adjacent.keys()
def getVertex_ID(self):
return self.id
def getWeight(self, neighbor):
return self.adjacent[neighbor]
def setDistance(self, dist):
self.distance = dist
def getDistance(self):
return self.distance
def setPrevious(self, prev):
self.previous = prev
def __str__(self):
return str(self.id) + "adjacent : " + str([x.id for x in self.adjacent])
class Graph:
def __init__(self):
self.vertDictionary = {}
self.numVertices = 0
def __iter__(self):
return iter(self.vertDictionary.values())
def addVertex(self, node):
self.numVertices += 1
newVertex = Vertex(node)
self.vertDictionary[node] = newVertex
return newVertex
def getVertex(self, node):
if node in self.vertDictionary:
return self.vertDictionary[node]
else:
return None
def addEdge(self, frm, to, cost = 0):
if frm not in self.vertDictionary:
self.addVertex(frm)
if to not in self.vertDictionary:
self.addVertex(to)
self.vertDictionary[frm].addNeighbor(self.vertDictionary[to], cost)
self.vertDictionary[to].addNeighbor(self.vertDictionary[frm], cost)
def getVertices(self):
return self.vertDictionary.keys()
def setPrevious(self, current):
self.previous = current
def getPrevious(self):
return self.previous
def getEdges(self):
edges = []
for v in G:
for w in v.getConnections():
v_id = v.getVertex_ID()
w_id = w.getVertex_ID()
edges.append((v_id, w_id, v.getWeight(w)))
return edges
def Dijkstra(G, s):
source = G.getVertex(s)
source.setDistance(0)
visited = {}
unvisitedQueue = [(v.getDistance(), v) for v in G]
heapq.heapify(unvisitedQueue)
while len(unvisitedQueue):
uv = heapq.heappop(unvisitedQueue)
currVert = uv[1]
visited[currVert] = True
for nbr in currVert.getConnections():
if currVert.getDistance() + currVert.getWeight(nbr) < nbr.getDistance():
nbr.setDistance(currVert.getDistance() + currVert.getWeight(nbr))
print("Updated: Current = %s Neighbour = %s New Distance = %s" %(currVert.getVertex_ID(), nbr.getVertex_ID(), nbr.getDistance()))
else:
print("Not Updated: Current = %s Neighbour = %s Distance = %s" %(currVert.getVertex_ID(), nbr.getVertex_ID(), nbr.getDistance()))
while len(unvisitedQueue):
heapq.heappop(unvisitedQueue)
unvisitedQueue = [(v.getDistance(), v) for v in G if v not in visited]
heapq.heapify(unvisitedQueue)
for v in G:
print(source.getVertex_ID(), "to", v.getVertex_ID(), "-->", v.getDistance())
ERROR -->
Traceback (most recent call last):
File "d:\Python\Final 450\Graph\Dijkstra's_Algo.py", line 124, in <module>
print(Dijkstra(G, "a"))
File "d:\Python\Final 450\Graph\Dijkstra's_Algo.py", line 86, in Dijkstra
heapq.heapify(unvisitedQueue)
TypeError: '<' not supported between instances of 'Vertex' and 'Vertex'
The error is happening because tuples are compared lexicographically. If two distances are the same, the comparison moves on to the Vertex objects themselves.
Two solutions readily come to mind. The first is simply to add a unique index to the tuple before the Vertex but after the distance. This is easy, and would work even if you didn't have access to the Vertex class:
unvisitedQueue = [(v.getDistance(), i, v) for i, v in enumerate(G) if v not in visited]
The second option is to modify Vertex to have a __lt__ magic method:
def __lt__(self, other):
return self.getDistance() < other.getDistance()
This is nice because you can heapify more directly now:
unvisitedQueue = [v for v in G if v not in visited]

how to get a cycle without using a loop in python?

im teaching my self python and i came across this interesting question which says:
Implement a generator cycle such that if we assign
i = cycle()
then repeated calls to
next(i)
return the values
me
myself
i
me
myself
i
...
I can't use a for loop but only a generator or stream. I cant use libraries. I need to output it 20 times
what I've tried so far but i cant manage to get the cycle to work:
def cycle(i):
saved = []
for el in m:
yield el
saved.append(el)
while saved:
for el in saved:
yield element
This is probably what you want:
def cycle(n=0):
saved=['me','myself','i']
while True:
yield saved[n]
n = (n+1) % 3
i = cycle()
for _ in range(20):
print(next(i))
If you don't want loops at all, try this:
class cycle:
def __init__(self,lst,maxstep = 20):
self.lst = lst
self.n = 0
self.len = len(lst)
self.maxstep = maxstep
def __next__(self):
if self.n>=self.maxstep: # remove this line
raise StopIteration # and this line, if you want infinite stream
ret = self.lst[self.n % self.len]
self.n += 1
return ret
obj = cycle(['me','myself','i'])
If you want to be able to call list on it, that is make it iterable:
class cycle():
def __init__(self,lst,maxstep = 20):
self.lst = lst
self.n = 0
self.i = 0
self.len = len(lst)
self.maxstep = maxstep
def __iter__(self):
while self.i < self.maxstep:
yield self.lst[self.i % self.len]
self.i += 1
def __next__(self):
if self.n>=self.maxstep:
raise StopIteration
ret = self.lst[self.n % self.len]
self.n += 1
return ret
obj = cycle([1, 2, 3])
print(list(obj))
# [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2]
# or
# print(next(obj))
# 1

N Puzzle in Python

I'm trying to build a solution to the N-Puzzle problem using breadth first search in Python.
My solution is adept at finding an answer if all of the numbers bar the zero are in order. e.g.
initial_state = [1,2,3,4,0,5,6,7,8]
or
initial_state = [1,2,3,4,5,6,7,0,8]
but fails with
initial_state = [1,2,5,3,4,0,6,7,8]
Pleases find below my implementation. If someone could point out the flaw in my logic it'd much appreciated.
Thanks in advance!
def right(state):
items = list(state)
i = items.index(0)
n = int(math.sqrt(len(items)))
if (i+1) % n != 0:
del items[i]
items.insert(i+1, 0)
return tuple(items)
else:
pass
def left(state):
items = list(state)
i = items.index(0)
n = int(math.sqrt(len(items)))
if i % n != 0:
del items[i]
items.insert(i-1, 0)
return tuple(items)
else:
pass
def up(state):
items = list(state)
i = items.index(0)
n = int(math.sqrt(len(items)))
if n**2 < i <= (n**2 - n):
del items[i]
items.insert(i+n, 0)
return tuple(items)
else:
pass
def down(state):
items = list(state)
i = items.index(0)
n = int(math.sqrt(len(items)))
if i > n:
del items[i]
items.insert(i-n, 0)
return tuple(items)
else:
pass
class Problem(object):
def __init__(self, initial, goal=None):
self.initial = initial
self.goal = goal
self.n = len(initial)
self.size = int(math.sqrt(self.n))
self.blank = self.initial.index(0)
self.top_row = [i for i in range(self.n) if i < self.size]
self.bottom_row = [i for i in range(self.n) if self.n - (self.size) <= i < self.n]
self.left_column = [i for i in range(self.n) if i % self.size == 0]
self.right_column = [i for i in range(self.n) if (i + 1) % self.size == 0]
def actions(self):
result_list = ["UP","DOWN","LEFT","RIGHT"]
return result_list
def result(self, state, action):
if action == "RIGHT":
return right(state)
if action == "LEFT":
return left(state)
if action == "UP":
return up(state)
if action == "DOWN":
return down(state)
def goal_test(self, state):
return state == self.goal
def path_cost(self, c):
return c + 1
class Node:
def __init__(self, state, parent=None, action=None, path_cost=0):
self.state = state
self.parent = parent
self.action = action
self.path_cost = path_cost
self.depth = 0
if parent:
self.depth = parent.depth + 1
def __repr__(self):
return "<Node %s>" % (self.state,)
def __lt__(self, node):
return self.state < node.state
def expand(self, problem):
return [self.child_node(problem, action)
for action in problem.actions() if self.child_node(problem,action) is not None]
def child_node(self, problem, action):
next = problem.result(self.state, action)
if next:
return Node(next, self, action,
problem.path_cost(self.path_cost))
else:
pass
def solution(self):
return [node.action for node in self.path()[1:]]
def path(self):
node, path_back = self, []
while node:
path_back.append(node)
node = node.parent
return list(reversed(path_back))
def __eq__(self, other):
return isinstance(other, Node) and self.state == other.state
def __hash__(self):
return hash(self.state)
def bfs(problem):
node = Node(problem.initial)
frontier = deque([node])
explored = set()
while frontier:
node = frontier.pop()
explored.add(node.state)
if problem.goal_test(node.state):
return node
for child in node.expand(problem):
if child.state not in explored and child not in frontier:
frontier.append(child)
return [child for child in explored]
p = Problem((1,2,5,3,4,0,6,7,8), (0,1,2,3,4,5,6,7,8))
bfs(p)
#returns
"""[(1, 2, 5, 3, 4, 0, 6, 7, 8),
(1, 2, 0, 5, 3, 4, 6, 7, 8),
(0, 1, 2, 5, 3, 4, 6, 7, 8),
(1, 2, 5, 3, 0, 4, 6, 7, 8),
(1, 2, 5, 0, 3, 4, 6, 7, 8),
(1, 0, 2, 5, 3, 4, 6, 7, 8)]"""
If you process the neighbors (children) of a node (state) by moving the space in UP, DOWN, LEFT, RIGHT order, the solution of an 8-puzzle with bfs starting with the initial state 1,2,5,3,4,0,6,7,8 will be like the following (you can check out where it's differing with your solution):
path_to_goal: ['Up', 'Left', 'Left']
cost_of_path: 3
You may want to refer to this https://sandipanweb.wordpress.com/2017/03/16/using-uninformed-informed-search-algorithms-to-solve-8-puzzle-n-puzzle/?frame-nonce=9e97a821bc for more details.
This condition in up is never true: if n**2 < i <= (n**2 - n).
And this condition in down is off by one: if i > n.
Whether the rest of your code is correct or not is unclear, but you need to debug the fundamentals of your board representation and manipulation code first.
In your space-moving code, I personally would turn your index into an x and y coordinate:
x, y = i % n, i // n
Then you can test more naturally: x>0 for left, x<n-1 for right, y<n-1 for up and y>0 for down.

Which data structure to use when implementing graph representation using adjacency list

I have a graph that is very big about 1,000,000 nodes and many edges. This is what i wanted to know which is the best suited data structure when implementing an adjacency list. Here are the objects that i keep track of
Edge list
Node to node connection list
I am coding with python so I used a set(because according to this it has a o(1) average insertion time) for edge list and a dictionary to node to node connection list(by making it completely hashable according to How to make an object properly hashable?). Here is my code
class node:
def __init__(self, name = ""):
self.__name = name
def getName(self):
return self.__name
def __str__(self):
return self.__name
def __hash__(self):
return hash(self.__name)
def __lt__(self, other):
if(type(self) != type(other)):
return NotImplemented
return self.__name.__lt__(other.__name)
def __eq__(self, other):
if(type(self)) != type(other):
return NotImplemented
return self.__name == other.__name
class Edge:
def __init__(self, name = "", node1 = None, node2 = None, weight = 0):
self.__name = name
self.__firstNode = node1
self.__secondNode = node2
self.__weight = weight
def getName(self):
return self.__name
def getFirstNode(self):
return self.__firstNode
def getSecondNode(self):
return self.__secondNode
def getWeight(self):
return self.__weight
def __lt__(self, other):
if(type(self) != type(other)):
return NotImplemented
return self.__name.__lt__(other.__name) and self.__firstNode.__lt__(other.__firstNode) and self.__secondNode.__lt__(other.__secondNode) and self.__weight.__lt__(other.__weight)
def __eq__(self, other):
if(type(self) != type(other)):
return NotImplemented
return self.__name == other.__name and self.__firstNode == other.__firstNode and self.__secondNode == other.__secondNode and self.__weight == other.__weight
def __str__(self):
return self.__name + " " + str(self.__firstNode) + " " + str(self.__secondNode) + " " + str(self.__weight)
def __hash__(self):
return hash(hash(self.__name) + hash(self.__firstNode) + hash(self.__secondNode) + hash(self.__weight))
class graph:
def __init__(self):
self.__nodeToNode = {}
self.__edgeList = set()
def addEdge(self, edge):
if(type(edge) != type(Edge())):
return False
self.__edgeList.add(edge)
if(not edge.getFirstNode() in self.__nodeToNode):
self.__nodeToNode[edge.getFirstNode()] = set()
self.__nodeToNode[edge.getFirstNode()].add(edge.getSecondNode())
if(not edge.getSecondNode() in self.__nodeToNode):
self.__nodeToNode[edge.getSecondNode()] = set()
self.__nodeToNode[edge.getSecondNode()].add(edge.getSecondNode())
return True
def getNodes(self):
return dict(self.__nodeToNode)
def getEdges(self):
return set(self.__edgeList)
import string
import random
import time
grp = graph()
nodes = [None] * 20000
for i in range(20000):
st = ''.join(random.SystemRandom().choice(string.ascii_letters) for i in range(10))
node1 = node(st)
nodes[i] = node1
current = time.time()
for i in range(3000000):
rdm = random.randint(0, 199)
rdm2 = random.randint(0, 199)
st = ''.join(random.SystemRandom().choice(string.ascii_letters) for i in range(10))
eg = Edge(st, nodes[rdm], nodes[rdm2])
grp.addEdge(eg)
last = time.time()
print((last - current))
nodes = grp.getNodes()
edges = grp.getEdges()
but this code runs very slowly can i make it faster? If so by using what data structure?
Let me introduce you a way to create an adjacency list:
Suppose you have the input like this:
4 4
1 2
3 2
4 3
1 4
The first line contains 2 numbers V and E, the next E lines defines an edge between two vertices.
You can either create a .txt file and read the input or directly type in via sys.stdin.read():
input = sys.stdin.read()
data = list(map(int, input.split()))
n, m = data[0:2]
data = data[2:]
edges = list(zip(data[0:(2 * m):2], data[1:(2 * m):2]))
x, y = data[2 * m:]
adj = [[] for _ in range(n)]
x, y = x - 1, y - 1
for (a, b) in edges:
adj[a - 1].append(b - 1)
adj[b - 1].append(a - 1)
Let's output the adjacency list adj:
>>> print(adj)
[[1, 3], [0, 2], [1, 3], [2, 0]]
adj[0] have two adj nodes: 1 and 3. Meaning the node 1 have two adj nodes: 2 and 4.
And now, if you want a directed, weighted graph, you just need to modify the input like this:
4 4
1 2 3 # edge(1, 2) has the weight of 3
3 2 1
4 3 1
1 4 2
input = sys.stdin.read()
data = list(map(int, input.split()))
n, m = data[0:2]
data = data[2:]
edges = list(zip(zip(data[0:(3 * m):3], data[1:(3 * m):3]), data[2:(3 * m):3]))
data = data[3 * m:]
adj = [[] for _ in range(n)]
cost = [[] for _ in range(n)]
for ((a, b), w) in edges:
adj[a - 1].append(b - 1)
cost[a - 1].append(w)
You store the weight in cost, and for example, cost[0][1] = 3, cost[0][3] = 2.
Hope this helped!

list with infinite elments

I need to operate on two separate infinite list of numbers, but could not find a way to generate, store and operate on it in python.
Can any one please suggest me a way to handle infinite Arithmetic Progession or any series and how to operate on them considering the fact the minimal use of memory and time.
Thanks every one for their suggestions in advance.
You are looking for a python generator instead:
def infinitenumbers():
count = 0
while True:
yield count
count += 1
The itertools package comes with a pre-built count generator.
>>> import itertools
>>> c = itertools.count()
>>> next(c)
0
>>> next(c)
1
>>> for i in itertools.islice(c, 5):
... print i
...
2
3
4
5
6
This is where the iterator comes in. You can't have an infinite list of numbers, but you can have an infinite iterator.
import itertools
arithmetic_progression = itertools.count(start,step) #from the python docs
The docs for Python2 can be found here
I have another python3 solution (read SICP chapter 3.5)
class Stream:
def __init__(self, head, tail):
self.head = head
self.tail = tail
self.memory = None
self.isDone = False
def car(self):
return self.head
def cdr(self):
if self.isDone:
return self.memory
self.memory = self.tail()
self.isDone = True
return self.memory
def __getitem__(self, pullFrom):
if pullFrom < 1 or self.memory == []:
return []
return [self.car()] + self.cdr()[pullFrom - 1]
def __repr__(self):
return "[" + repr(self.car()) + " x " + repr(self.tail) + "]"
def map(self, func):
if self.memory == []:
return []
return Stream(func(self.car()), lambda: Stream.map(self.cdr(), func))
def from_list(lst):
if lst == []:
return []
return Stream(lst[0], lambda:
Stream.from_list(lst[1:]))
def filter(self, pred):
if self.memory == []:
return []
elif pred(self.car()):
return Stream(self.car(), lambda: Stream.filter(self.cdr(), pred))
else:
return self.cdr().filter(pred)
def sieve(self):
return Stream(self.car(), lambda: self.cdr().filter(lambda n: n % self.car() > 0).sieve())
def foreach(self, action, pull = None):
if pull is None:
action(self.car())
self.cdr().foreach(action, pull)
elif pull <= 0:
return
else:
action(self.car())
self.cdr().foreach(action, pull-1)and run:
a = Stream(0, lambda: a.map((lambda x: x + 1)))
print(a[10])
which returns:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] .
But streams are lazily evaluated, so:
>>> a = Stream(0, lambda: a.map((lambda x: x + 1)))
>>> print(a)
prints:
[0 x [...]]
To create an object that acts like a "mutable" infinite list, you can overload the __getitem__ and __setitem__ methods in a class:
class infinite_list():
def __init__(self, func):
self.func = func
self.assigned_items = {}
def __getitem__(self, key):
if key in self.assigned_items:
return self.assigned_items[key]
else:
return self.func(key)
def __setitem__(self, key , value):
self.assigned_items[key] = value
Then, you can initialize the "infinite list" with a lambda expression and modify an item in the list:
infinite_thing = infinite_list(lambda a: a*2)
print(infinite_thing[1]) #prints "2"
infinite_thing[1] = infinite_thing[2]
print(infinite_thing[1]) #prints "4"
Similarly, it is possible to create an "infinite dictionary" that provides a default value for each missing key.
Perhaps the natural way to generate an infinite series is using a generator:
def arith(a, d):
while True:
yield a
a += d
This can be used like so:
print list(itertools.islice(arith(10, 2), 100))
My solution is:
from hofs import *
def cons_stream(head,tail):
return [head,tail,False,False]
def stream_cdr(strm):
if strm[2]:
return strm[3]
strm[3] = strm[1]()
strm[2] = True
return strm[3]
def show_stream(stream, num = 10):
if empty(stream):
return []
if num == 0:
return []
return adjoin(stream[0], show_stream(stream_cdr(stream), num - 1))
def add_streams(a , b):
if empty(a):
return b
if empty(b):
return a
return cons_stream(a[0] + b[0] , lambda : add_streams( stream_cdr(a), stream_cdr(b)))
def stream_filter( pred , stream ):
if empty(stream):
return []
if pred(stream[0]):
return cons_stream(stream[0], lambda : stream_filter(pred, stream_cdr(stream)))
else:
return stream_filter( pred , stream_cdr( stream ))
def sieve(stream):
return cons_stream(stream[0] , lambda : sieve(stream_filter(lambda x : x % stream[0] > 0 , stream_cdr(stream))))
ones = cons_stream(1, lambda : ones)
integers = cons_stream(1, lambda : add_streams(ones, integers))
primes = sieve(stream_cdr(integers))
print(show_stream(primes))
Copy the Python code above.
When I tried it, i got [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] which is 10 of an infinite list of primes.
You need hofs.py to be
def empty(data):
return data == []
def adjoin(value,data):
result = [value]
result.extend(data)
return result
def map(func, data):
if empty(data):
return []
else:
return adjoin(func(data[0]), map(func, data[1:]))
def keep(pred, data):
if empty(data):
return []
elif pred(data[0]):
return adjoin( data[0] , keep(pred, data[1:]))
else:
return keep(pred, data[1:])
I assume you want a list of infinite numbers within a range. I have a similar problem, and here is my solution:
c = 0
step = 0.0001 # the difference between the numbers
limit = 100 # The upper limit
myInfList = []
while c <= limit:
myInfList.append(c)
c = c + step
print(myInfList)

Categories