0
t = 8
string = "1 2 3 4 3 3 2 1"
string.replace(" ","")
string2 = [x for x in string]
print string2

for n in range(t-1):
    string2.remove(' ')

print string2

def remover(ca):
    newca = []
    print len(ca)

    if len(ca) == 1:
        return ca
    else:
        for i in ca:
            newca.append(int(i) - int(min(ca)))

    for x in newca:
        if x == 0:
            newca.remove(0)

    print newca
    return remover(newca)

print (remover(string2))

It's supposed to be a program that takes in a list of numbers, and for every number in the list it subtracts from it, the min(list). It works fine for the first few iterations but not towards the end. I've added print statements here and there to help out.

EDIT:

t = 8

string = "1 2 3 4 3 3 2 1"

string = string.replace(" ","")

string2 = [x for x in string]

print len(string2)

def remover(ca):

    newca = []

    if len(ca) == 1: return()

    else:
        for i in ca:
            newca.append(int(i) - int(min(ca)))

    while 0 in newca:
        newca.remove(0)

    print len(newca)

    return remover(newca)


print (remover(string2))
kalin
  • 155
  • 9
  • Please describe what input the user is supposed to enter, what kind of output you expect to see, and what output you're getting instead. – Kevin Nov 04 '14 at 19:14
  • 1
    By the way, I don't think this is related to your problem, but `string.replace` doesn't do anything unless you assign the result to something. For example, `string = string.replace(" ","")`. – Kevin Nov 04 '14 at 19:16
  • It's also not totally clear what the function of t is supposed to be here - why is the user inputting it? – furkle Nov 04 '14 at 19:17
  • what i think is happening is that when when it comes down to [0,1,0,0], and i remove the first 0, the loop doesnt go till the 4th zero to even remove it.. – kalin Nov 04 '14 at 19:18
  • edited guys, sorry completely forgot about putting the input in the code here – kalin Nov 04 '14 at 19:19
  • Why are you having the user enter in the number of items in the first place? You can just use `len` and then you don't have to make work for the user/risk exception. – furkle Nov 04 '14 at 19:20
  • @Kevin just string.replace(" ","") does seem to work for me though. – kalin Nov 04 '14 at 19:20
  • If by "work" you mean "doesn't cause Python to crash", then yes, I agree that it works. If you mean "it causes the value of `string` to change", then I disagree. – Kevin Nov 04 '14 at 19:21
  • @furkle its for this challenge in hackerrank, which wants the program to take in an input – kalin Nov 04 '14 at 19:22
  • What do you mean by 'funny'? – Piotr Dabkowski Nov 04 '14 at 19:22
  • Right, and I'm telling you that you're going about it the wrong way. There is no point in having a user enter the number of items he's about to type. It wastes their time and you can't even trust the input. – furkle Nov 04 '14 at 19:23
  • @Kevin I'm confused, is there a difference between the two even though they give the same result? – kalin Nov 04 '14 at 19:23
  • 1
    @kalin Yes - literally nothing is done by just typing `str.replace(" ", "")`. It does not alter the string it is called on. Rather, it just returns a new string. You have to use `str = str.replace(" ", "")`. – furkle Nov 04 '14 at 19:24
  • 1
    @kalin, [this](http://ideone.com/GYrcrY) sample code demonstrates the difference between replacement without assignment, and replacement with assignment. Namely, that the first one doesn't do anything. – Kevin Nov 04 '14 at 19:24
  • @furkle, i'm a beginner so bear with me. is there any reference that i could read up on for what you're describing? It's hard to follow what you're saying because both the methods seem to give me the same output – kalin Nov 04 '14 at 19:28
  • Just to make sure, are you testing out `replace` on the interactive command line? (the thing where you type into a ">>>" prompt). Because `string.replace` _does_ show the replaced result when you enter it into a prompt, but this doesn't mean that `string` has actually changed. – Kevin Nov 04 '14 at 19:30
  • @kevin I saved a .py file on sublimetext and just ran it with python file.py on the terminal. string.replace() still works fine. and i get the same output in the python prompt as well. – kalin Nov 04 '14 at 19:32
  • @Kevin Even worse, if you change that line so that it actually reassigns the string, the whole program breaks. I think it's because he's already fulfilling that function another place. – furkle Nov 04 '14 at 19:33
  • @kalin You get that output because it's printing what's been returned. *Nothing* is done to `string` if the entirety of your statement is just `string.replace()`. – furkle Nov 04 '14 at 19:34
  • @furkle if you look at the code in my question, theres just one line on it's own with string.replace(' ','') and the output for it is used in the next line. doesn't this contradict with what you're asserting? – kalin Nov 04 '14 at 19:37
  • @kalin No, because that's not how anything works in python. You can't use the output of a value you create on one line on another line unless you save it somehow, and you haven't saved it. Please believe all of us about this. – furkle Nov 04 '14 at 19:39
  • @furkle http://stackoverflow.com/questions/9189172/python-string-replace – kalin Nov 04 '14 at 19:43
  • @kalin This says literally what I said it did. "X.replace("C:","c") returns a copy of X with replacements made." If you don't assign the return value (as you're not), you've done absolutely nothing. – furkle Nov 04 '14 at 19:44
  • yes thats why i posted the link. thanks for that. I get why my code appeared to work now. I removed the spaces twice, ( again after string.replace()ing it) if you notice the first for loop in the code! thanks – kalin Nov 04 '14 at 19:48

3 Answers3

2
for x in newca:
    if x == 0:
        newca.remove(0)

Iterating over a list and removing things from it at the same time can lead to strange and unexpected behvaior. Try using a while loop instead.

while 0 in newca:
    newca.remove(0)

Or a list comprehension:

newca = [item for item in newca if item != 0]

Or create yet another temporary list:

newnewca = []
for x in newca:
    if x != 0:
        newnewca.append(x)

print newnewca

return remover(newnewca)
Kevin
  • 74,910
  • 12
  • 133
  • 166
  • 1
    Or just use `filter(None, newca)`. – 9000 Nov 04 '14 at 19:24
  • Thanks Kevin, I get what was going wrong now, and the program runs as expected now :D – kalin Nov 04 '14 at 19:33
  • Kevin could you help me with this last bit. Ive added the code for the final program in the question. It prints fine until the last line where it is () instead of just breaking at 1 in the previous line. How do i break the 'if' loop without printing anything? – kalin Nov 04 '14 at 20:03
  • 1
    Try removing the `print` on the final line. So just `remover(string2)` instead of `print (remover(string2))`. – Kevin Nov 04 '14 at 20:04
1

(Not a real answer, JFYI:)

Your program can be waaay shorter if you decompose it into proper parts.

def aboveMin(items):
  min_value = min(items) # only calculate it once
  return differenceWith(min_value, items)

def differenceWith(min_value, items):
  result = []
  for value in items:
    result.append(value - min_value)
  return result

The above pattern can, as usual, be replaced with a comprehension:

def differenceWith(min_value, items):
  return [value - min_value for value in items]

Try it:

>>> print aboveMin([1, 2, 3, 4, 5])
[0, 1, 2, 3, 4]

Note how no item is ever removed, and that data are generally not mutated at all. This approach helps reason about programs a lot; try it.

9000
  • 39,899
  • 9
  • 66
  • 104
  • damn 9000, i need to start defining functions for my programs. ive noticed all my submissions for challenges are ugly as hell and slow even though they end up working. thanks a lot – kalin Nov 04 '14 at 19:36
  • Yes, you need to start _with_ defining functions in your programs, and composing them as they appear. Top to bottom or bottom to top, doesn't matter. Once you have a couple of lines that are logically sound, make a function out of them, and give it a good descriptive name (the latter _is_ hard). This is perfectly doable while toying with Python REPL, BTW, even the top-down approach works good. – 9000 Nov 04 '14 at 22:03
0

So IF I've understood the description of what you expect,

I believe the script below would result in something closer to your goal.

Logic:

  • split will return an array composed of each "number" provided to raw_input, while even if you used the output of replace, you'd end up with a very long number (you took out the spaces that separated each number from one another), and your actual split of string splits it in single digits number, which does not match your described intent
  • you should test that each input provided is an integer
  • as you already do a print in your function, no need for it to return anything
  • avoid adding zeros to your new array, just test first

string = raw_input()

array = string.split()
intarray = []
for x in array:
  try:
    intarray.append(int(x))
  except:
    pass

def remover(arrayofint):
  newarray = []
  minimum = min(arrayofint)
  for i in array:
    if  i > minimum:
      newarray.append(i - minimum)
  if len(newarray) > 0:
    print newarray
    remover(newarray)

remover(intarray)
Olivier
  • 2,571
  • 1
  • 17
  • 25