Saelyth
Saelyth

Reputation: 1734

string replacement of fixed positions in python

i'm trying to do a Trivia program and i'm getting issues with the answers. What i want is to replace the characters of the answers to display as hints. Example:

answer = "I am just an example"
hintwouldbe = "I a_ j___ a_ e______"
hint2mightbe = "I am j___ an e_a___e"

i am not really sure how to make it. Tried with loops (for c in answer) and string.replace methods. Also tried with some re.translate and dicts but i'm getting really big codes and hard to understand. Ther must be an easer way so... here i am.

Which way do you think would be the most efficient/easier to accomplish that?

Edit It would be great if i could choose what positions to replace. for example: if the word has 6 characters, replace 1,3 and 6 characters with a _

Edit2: Right answer

After a bit change, i choose Thomas Orozco answer as valid, is quite easy to understand and re-create:

    from random import random
    answer = "anything in here"
    pista = [char if random() < 0.8 else "_" for char in answer]
    pista2 = "".join(pista)
    print(pista2)

Upvotes: 2

Views: 1001

Answers (4)

user2314737
user2314737

Reputation: 29307

Substitute characters at prescribed positions:

answer = "I am just an example"   
''.join('_' if i in (1,3,6) else answer[i] for i in range(0, len(answer)))

To avoid substituting white spaces:

import string
answer = "I am just an example" 
def pr((c,i,L)):
 if (i in L and c in string.letters + string.digits):
  return '_'
 else:
  return c

''.join(map(pr,((answer[i],i,(1,3,6)) for i in range(len(answer)))))

and randomly (assuming you don't want to substitute white spaces):

answer = "I am just an example"
import string
import random
''.join('_' if random.randint(0, 1) and i in string.letters + string.digits else i for i in answer)

Upvotes: 1

dansalmo
dansalmo

Reputation: 11686

This method automatically replaces all but the first letter of each word with '_', then will allow an index based re-fill of the hint letters. It uses three list comprehensions:

def hint(a, hidxs):
    return ''.join(c[i in idxs] for i, c in enumerate(a))

a = zip(' '.join(w[0] + '_'*(len(w)-1) for w in answer.split()), answer)
_idxs = [i for i, c in enumerate(hint(a, [])) if c == '_']

Here is how to use them:

>>> answer = "I am just an example"
>>> a = zip(' '.join(w[0 ]+ '_'*(len(w)-1) for w in answer.split()), answer)
>>> _idxs = [i for i, c in enumerate(hint(a, [])) if c == '_']
>>> _idxs #list of indexes for every '_'
[3, 6, 7, 8, 11, 14, 15, 16, 17, 18, 19]
>>> hidxs=[]
>>> print 'Hint 1:', hint(a, hidxs)
Hint 1: I a_ j___ a_ e______
>>> hidxs=[6]
>>> print 'Hint 2:', hint(a, hidxs)
Hint 2: I a_ ju__ a_ e______
>>> hidxs=[6, 14]
>>> print 'Hint 3:', hint(a, hidxs)
Hint 3: I a_ ju__ a_ ex_____
>>> hidxs=[6, 14, 17]
>>> print 'Hint 4:', hint(a, hidxs)
Hint 4: I a_ ju__ a_ ex__p__
>>> print 'Answer:', hint(a, _idxs)
Answer: I am just an example

A program that randomly hints would be:

from random import shuffle
def hint(a, hidxs):
    return ''.join(c[i in idxs] for i, c in enumerate(a))

def all_hints(answer):
    a = zip(' '.join(w[0 ]+ '_'*(len(w)-1) for w in answer.split()), answer)
    _idxs = [i for i, c in enumerate(hint(a, [])) if c == '_']
    shuffle(_idxs)
    hints = []
    print 'Press enter for next hint:'
    for i in _idxs:
        print 'Hint:', hint(a, hints),
        hints.append(i)
        raw_input()
    print 'Answer:', hint(a, hints)

Upvotes: 0

Max Li
Max Li

Reputation: 5199

You should place the logic you have in mind (as in your example, in words of 6 letters replace 1-st, 3-rd and 6-th) into structures (e.g. dictionaries). Then, split the sentence into words and apply your logic to them. Here's the function that exchanges the needed positions in the word with _:

def exchange(word,positions):
    chars=list(word)
        w=""
    for i in range(1,len(chars)+1):
        if i in positions:
            w+='_'
        else:
            w+=chars[i-1]
    return w

Put the logic into dictionary (7 - to catch the word 'example', and 4 to catch 'just'):

d={7:[1,3,6],4:[range(2,4+1)]}

And finally apply the logic:

words=answer.split() # split the sentence into word
' '.join(map(lambda x: exchange(x,d.get(len(x),[])),words)) # apply the logic and join results
>>> 'I am j___ an _x_mpl_'

Upvotes: 1

Thomas Orozco
Thomas Orozco

Reputation: 55199

A string isn't an appropriate representation for what you're trying to do, a list would do better.

import random

def make_hint(chars, frequency):
    hint_chars = [char if random.random() < frequency else "_" for char in chars]
    return "".join(hint_chars)

answer = "I am just an example"

print make_hint(answer, 0.3)
print make_hint(answer, 0.5)

Of course, this is only an example. Here, I'm using random to display 30% or 50% of characters, but you could use a different implementation.

Remember that you could first call .split() on answer to split it in words before running the transformation:

print " ".join(make_hint(word, 0.3) for word in answer.split())

Upvotes: 2

Related Questions