python dictionary and deque to print required output based on some condition - python-3.x

I have CSV File which contains some data Produced from Mining
I wanted to print it as shown in required format
Required Format
A -> B -> C -> D -> E -> F
A -> B -> C -> I
X -> Y -> Z
X -> Y -> P -> Q
A -> B -> K -> L
a.csv File
## code
from collections import deque
import pandas as pd
data = pd.read_csv("a.csv")
data['Start'] = data['Start'].str.replace(' ','_')
data['End'] = data['End'].str.replace(' ','_')
fronts = dict()
backs = dict()
sequences = []
position_counter = 0
selector = data.apply(lambda row: row.str.extractall("([\w+\d]+)"), axis=1)
for relation in selector:
front, back = relation[0]
llist = deque((front, back))
finb = front in backs.keys()
if finb:
position = backs[front]
llist2 = sequences[position]
back_llist2 = llist2.pop()
llist = llist2 + llist
sequences[position] = llist
backs[llist[-1]] = position
if front in fronts.keys():
del fronts[front]
if back_llist2 in backs.keys():
del backs[back_llist2]
if not finb:
sequences.append(llist)
fronts[front] = position_counter
backs[back] = position_counter
position_counter += 1
data = []
for s in sequences:
data.append(' -> '.join(str(el) for el in s))
data
What I'm Getting is:
'A -> B -> C -> D -> E -> F'
'C -> I'
'A -> N -> A'
'X -> Y -> Z'
'Y -> P -> Q'
'B -> K -> L'
'X1 -> Y1'

You need to search the existing paths for the starting element of the new row. If found, append to the existing path or copy the path and append the new end element.
Try this code:
ss = '''
A B
B C
C D
D E
E F
C I
A N
N A
X Y
Y Z
Y P
P Q
B K
K L
X1 Y1
'''.strip()
lst = []
for r in ss.split('\n'):
lst.append(r.split())
################
paths = []
for e in lst: # each row in source data
pnew = [] # new path
for p in paths:
if e[0] in p: # if start in existing path
if p.index(e[0]) == len(p)-1: # if end of path
p.append(e[1]) # add to path
else:
pnew.append(p[:p.index(e[0])+1]+[e[1]]) # copy path then add
break
else: # loop completed, not found
paths.append(list(e)) # create new path
if len(pnew): # copied path
paths.extend(pnew) # add copied path
print('\n'.join([' => '.join(e) for e in paths]))
Output
A => B => C => D => E => F
A => B => C => I
A => N => A
X => Y => Z
X => Y => P => Q
A => B => K => L
X1 => Y1
The A->N->A and X1->Y1 are correct based on the source data. I don't know why they would be excluded in the desired output.

Related

Python Search for Pattern in list of string elements

I'm searching for a pattern in a list of string elements.
As far my code is working fine, but some data is unable to produce required result.
Code
ss = '''
X A
B A
A C
A D
E A
A F
'''.strip()
lst = []
for r in ss.split('\n'):
lst.append(r.split())
paths = []
for e in lst:
# each row in source data
pnew = [] # new path
for p in paths:
if e[0] in p: # if start in existing path
if p.index(e[0]) == len(p)-1: # if end of path
p.append(e[1]) # add to path
else:
pnew.append(p[:p.index(e[0])+1]+[e[1]]) # copy path then add
break
else: # loop completed, not found
paths.append(list(e)) # create new path
if len(pnew): # copied path
paths.extend(pnew) # add copied path
print('\n'.join([' -> '.join(e) for e in paths]))
what i'm getting is
X -> A -> C
B -> A
X -> A -> D
E -> A
X -> A -> F
what my requried result is
B -> A -> C
X -> A -> D
E -> A -> F
X -> A -> C
B -> A -> D
B -> A -> F
X -> A- > F
Based on Cr & Dr I'm Trying to get the pattern (Cr & Dr are optional)
X A Cr
B A Cr
A C Dr
A D Dr
E A Cr
A F Dr
It's easier to handle this with pandas:
import pandas as pd
from io import StringIO
ss = '''
X A
B A
A C
A D
E A
A F
'''.strip()
df = pd.read_csv(StringIO(ss), sep=' ', names=['source', 'target'])
df = df.merge(df, how='inner', left_on='target', right_on='source')
df = df[['source_x', 'target_x', 'target_y']]
df.apply(lambda x: ' -> '.join(x), axis=1).sort_values()

Diagonals with same characters - Python

The program must accept a character matrix of size RxC as the input. The program must print the number of diagonals that parallel to the top-left to bottom-right diagonal and having the same characters in the matrix.
def lower_diagonals(row,matrix):
# a list to store the lower diagonals
# which are || to top left to bottom right
d=[]
# Iterating from the second row till the last row
for i in range(1,row):
nop,dummy = [],0
for j in range(i,row):
try:
nop.append(matrix[j][dummy])
except:
break
dummy+=1
d.append(nop)
return d
def upper_diagonals(col,matrix):
# a list to store the lower diagonals
# which are || to top left to bottom right
d=[]
# Iterating from 1st column till the last column
for i in range(1,col):
dum , nop = i,[]
# Iterating till the last before row
for j in range(row-1):
try:
nop.append(matrix[j][dum])
except:
break
dum+=1
d.append(nop)
return d
def diagonals(matrix,row,col):
return lower_diagonals(row,matrix) + upper_diagonals(col,matrix)
row,col = map(int,input().input().split())
matrix =[input().strip().split(' ') for i in range(row)]
new_matrix = diagonals(matrix,row,col)
t=0
for i in new_matrix:
if len(list(set(i))) == 1 : t+=1
print(t)
Example :
Input :
4 4
u m o a
h n a o
y h r w
b n h e
Output:
4
Input :
5 7
G a # z U p 3
e G b # n U p
a e G m # e U
L l e g k # t
j L a e G s #
Output:
6
My code works perfect for all the above mentioned cases but it fails for the below case
Input :
2 100
b h D k 2 D 9 I e Q # * B 5 H Z r q u n P C 4 a e K l 2 E p 6 R V v 0 d 8 x C F P M F C e m K H O y # 0 I T r P 8 P N 9 Z 7 S J J P c L g x X f 5 1 o i Y V Y G Y 9 A E O 2 r 2 # S 8 z D 6 a q r i k r
V o 4 T M m z p 6 G H D Y a 6 t O 7 # w y t 2 m A 1 a + 0 p t P D z 7 V N T x + I t 4 x x y 1 Q G M t M 0 v d G e u 4 b 8 m D # I v D i T 1 u L f e 1 Y E Y q Y c A 8 P 2 q 2 A 8 y b u E 3 c 1 s M n X
Expected Output:
9
My Output:
100
Can anyone help me in structuring the logic for this case Thanks in advance
Note :
2<=R,C<=100
Time limit : 500ms
I think i probably found a logic for my problem
r,c = map(int,input().strip().split())
mat = []
for i in range(r):
l = list(map(str,input().strip().split()))
mat.append(l[::-1])
count = 0
for i in range(r+c-1):
l = []
for row in range(r):
for col in range(c):
if row+col == i:
l.append(mat[row][col])
l = list(set(l))
if len(l) == 1:
count+=1
print(count)

Applying PDA transitions over a list of input strings in haskell

I'm trying to implement a PDA in Haskell based on my lecturer's notes, she has described the general process to us and left the actual function implementation up to us. I feel like I have the majority of it working bar one little bug in the nextsteps function.
The rules of the PDA are as follows:
[((1,"a",""),(1,"a")),((1,"b",""),(1,"b")),((1,"a",""),(2,"")),((1,"b",""),(2,"")),((1,"",""),(2,"")),((2,"a","a"),(2,"")),((2,"b","b"),(2,""))]
run :: PDA -> String -> Result
run _ "" = Reject
run (state,finalState,rules) str = findpath [(state,str,""(state,finalState,rules)
data Result = Accept | Reject deriving Show
type PDA = (Int,[Int],[Transition])
-- Takes in the start state, the current value read by the input string, the current stack and the new state along with the change to the stack
-- ((1,"a",""),(1,"a"))
type Transition = ((Int, String, String),(Int,String))
-- contains the current state, current input string and current state of the stack
-- (1,"abba","ba")
type Configuration = (Int, String, String)
--if the list of configurations isnt accepted, apply the PDA transitions to it and try again
findpath :: [Configuration] -> PDA -> Result
findpath [] pda = Reject
findpath (h:t) (a,b,c) = if accept (h:t) b == True then Accept else findpath (nextsteps (h:t) c) (a,b,c)
accept' :: Configuration -> [Int] -> Bool
accept' config [] = False
accept' (x,y,z) [a] = if x == a && y == "" && z == "" then True else False
accept:: [Configuration] -> [Int] -> Bool
accept [] _ = False
accept _ [] = False
accept (h:t) finalState = if accept' h finalState then True else accept t finalState
-- apply a given transition to a configuration based on the values in the configuration and transition
step :: Configuration -> Transition -> [Configuration]
step (a,b,"")((d,"",""),(g,"")) = if a == d then [(g,b,"")] else []
step (a,(b:bs),"")((d,"",""),(g,h)) = if a == d then [(g,bs,[b])] else []
step (a,(b:bs),"") ((d,"",f),(g,"")) = if a == d then [(g,(b:bs),f)] else []
step (a,(b:bs),"") ((d,"",f),(g,h)) = if a == d then [(g,(b:bs),h)] else []
step (a,(b:bs),"") ((d,[e],""),(g,"")) = if a == d && b == e then [(g,bs,"")] else []
step (a,(b:bs),"") ((d,[e],""),(g,h)) = if a == d && b == e then [(g,bs,[b])] else []
step (a,(b:bs),"") ((d,[e],f),(g,"")) = if a == d && b == e then [(g,bs,"")] else []
step (a,(b:bs),"") ((d,[e],f),(g,h)) = if a == d && b == e then [] else []
step (a,b,c) ((d,"",""),(g,"")) = if a == d then [(g,b,c)] else []
step (a,(b:bs),c) ((d,"",""),(g,h)) = if a == d then [(g,bs,c)] else []
step (a,b,(c:cs))((d,"",[f]),(g,"")) = if a == d && c == f then [(g,b,cs)] else []
step (a,b,(c:cs)) ((d,"",[f]),(g,h)) = if a == d && c == f then [(g,b,cs++h)] else []
step (a,(b:bs),c) ((d,[e],""),(g,"")) = if a == d then [(g,bs,c)] else []
step (a,(b:bs),c) ((d,[e],""),(g,h)) = if a == d && b == e then [(g,bs,[b]++c)] else []
step (a,(b:bs),(c:cs)) ((d,[e],[f]),(g,""))= if a == d && b == e && c == f then [(g,bs,cs)] else []
step (a,(b:bs),(c:cs)) ((d,[e],[f]),(g,h)) = if a == d && b == e && c == f then [(g,bs,cs++h)] else []
-- apply the entire ruleset of the PDA over one configuration and return a list of the results
steps :: Configuration -> [Transition] -> [Configuration]
steps config [] = []
steps (a,b,c) (h:t) = if b /= "" then step (a,b,c) h ++ steps (a,b,c) t else []
-- take in a list of configurations and apply the entire rulest over each configuration and return a list of results
nextsteps :: [Configuration] -> [Transition] -> [Configuration]
nextsteps config [] = []
nextsteps (h : t) rules = steps h rules ++ nextsteps t rules
The program works for certain strings and not others, I'm certain its to do with my nextsteps function. In my lecturer's notes she gives the example
nextsteps [(1,"bbabba","a"),(2,"abbabba",""),(2,"bbabba","") rules = [(1,"babba","ba"),(2,"babba","a"),(2,"bbabba","a")]
However, when I call the function on the exact same inputs I get [(1,"babba","ba"),(2,"babba","a"),(2,"babba","a"),(2,"bbabba","a")].
I'm not sure where this extra duplicate value is coming from and is the main reason why strings that shouldn't be excepted are getting accepted. I have tried removing the tail of the configurations list and only applying the steps function to the head of the list, and that will make sure any list that shouldn't be accepted is Rejected, but also Rejected inputs that should be Accepted.

How to add line in code in python console

How to add new line in python. for example, I would like to print the rest of a sentence in a new line. but instead of putting "\n", I will automate it to type to a new line for every six words.
Morse code translator
sth like:
def wrapper(words, n):
to_print = ''
for i in range(0, len(words.split()), n):
to_print += ' '.join(words.split()[i:i+n]) + '\n'
return to_print
and result is:
print(wrapper('a b c d e f g h i j k l m n o p r s t u w x y z', 6))
a b c d e f
g h i j k l
m n o p r s
t u w x y z

'where' inside other expression

I can use let inside other expression.
foo n = (let a = True in (\x -> a)) 3
foo' n | n == 1 = let a = True in a
| n /= 1 = False
But I can't do the same with where
foo n = ((\x -> a) where a = True) 3
foo' n | n == 1 = a where a = True
| n /= 1 = False
1:20: parse error on input `where'
Is it really impossible in haskell or just my mistake?
let is an expression while where is a clause. where is bound to syntactic constructs, let can be used anywhere expressions can.
You could of course write it like this:
foo n = ((\x -> a)) 3 where a = True
foo' n | n == 1 = a
| n /= 1 = False
where a = True
or like this:
foo n = (\a -> (\x -> a) 3) True
You need to put the where clause at the end:
foo n = ((\x -> a)) 3
where a = True
foo' n | n == 1 = a
| n /= 1 = False
where a = True
The difference is that let is an expression, whereas where requires some other construct to be bound to. See let vs where
let ... in ... is for introducing name bindings in an expression.
where is convenience syntax for giving local auxiliary definitions along with an equation. You can only use it as part of an equation (at the end), not in the middle of an arbitrary expression.
Their usage is not the same.
The claim that let is an expression is a bit off, it seems to me; in a do block it is a statement, though we say that there it abbreviates let ... in. The thing to say, I think, is
let_in_ :: Statement -> Expression -> Expression
_where_ :: Statement -> Statement -> Statement
Thus the first part of a let is a statement and can be modified by a where. So for example
foo n = (let a = b where b = True in (\x -> a)) 3
bip = do
let a = b where b = let c = d where d = True in c
return a
Similarly we can maybe say something like this:
case_of_ :: Expression -> [Statement] -> Expression
so that e.g.
z x = case even x of
True -> d where d = x + 1
False -> w - 1 where w = let a = x in a + 1

Resources