Jump to content

Haskell List modification

79wjd

I'm just starting to learn Haskell, and I'm not really sure how to accomplish what I'm looking to do. I'm given a list and I then want to decrement the number in the highest index and increment the number in the second highest index by its index (where the first element has an index of 1 and not 0). So, [2,0,0]->[1,2,0]->[0,4,0]->[0,3,1]->etc... The function will be passed a list of integers that can be any length, so func [1,2,0] should result in [0,4,0] being returned.

 

I'm thinking some base cases but for the recursive step I'm having a lot of trouble. It's obviously not right and it's partially pseudo code as I'm not sure how I would actually write it in Haskell. 


func (x:xs)

    | x>0 = x-1

    | x>0 head(xs)=head(xs)+length(xs)

    | func xs

PSU Tier List | CoC

Gaming Build | FreeNAS Server

Spoiler

i5-4690k || Seidon 240m || GTX780 ACX || MSI Z97s SLI Plus || 8GB 2400mhz || 250GB 840 Evo || 1TB WD Blue || H440 (Black/Blue) || Windows 10 Pro || Dell P2414H & BenQ XL2411Z || Ducky Shine Mini || Logitech G502 Proteus Core

Spoiler

FreeNAS 9.3 - Stable || Xeon E3 1230v2 || Supermicro X9SCM-F || 32GB Crucial ECC DDR3 || 3x4TB WD Red (JBOD) || SYBA SI-PEX40064 sata controller || Corsair CX500m || NZXT Source 210.

Link to comment
Share on other sites

Link to post
Share on other sites

I'm a bit rusty in haskell, but as I see it you would need the first two elements as variables not just the first.

from your code would be something like this

func (x:xs)

    | x>0 = x-1

    | x>0 head(xs)=head(xs)+length(xs)

    | (x:func xs)

As I said, it's been a while so I don't remember if this is the way to do it or if the parenthesis are necessary.

 

As I'm writing this, it occurs to me that you would need to create the case that there are not enough elements in xs

The best way to measure the quality of a piece of code is "Oh F*** "s per line

Link to comment
Share on other sites

Link to post
Share on other sites

3 minutes ago, espurritado said:

I'm a bit rusty in haskell, but as I see it you would need the first two elements as variables not just the first.

from your code would be something like this


func (x:xs)

    | x>0 = x-1

    | x>0 head(xs)=head(xs)+length(xs)

    | (x:func xs)

As I said, it's been a while so I don't remember if this is the way to do it or if the parenthesis are necessary.

 

As I'm writing this, it occurs to me that you would need to create the case that there are not enough elements in xs

I have a base case for an empty and a singleton list, so that should take care of that.

 

The second if (?) line is getting (or that's what I'm trying to do) the next element in the list so I can add to it. 

PSU Tier List | CoC

Gaming Build | FreeNAS Server

Spoiler

i5-4690k || Seidon 240m || GTX780 ACX || MSI Z97s SLI Plus || 8GB 2400mhz || 250GB 840 Evo || 1TB WD Blue || H440 (Black/Blue) || Windows 10 Pro || Dell P2414H & BenQ XL2411Z || Ducky Shine Mini || Logitech G502 Proteus Core

Spoiler

FreeNAS 9.3 - Stable || Xeon E3 1230v2 || Supermicro X9SCM-F || 32GB Crucial ECC DDR3 || 3x4TB WD Red (JBOD) || SYBA SI-PEX40064 sata controller || Corsair CX500m || NZXT Source 210.

Link to comment
Share on other sites

Link to post
Share on other sites

21 minutes ago, djdwosk97 said:

I'm just starting to learn Haskell, and I'm not really sure how to accomplish what I'm looking to do. I'm given a list and I then want to decrement the number in the highest index and increment the number in the second highest index by its index (where the first element has an index of 1 and not 0). So, [2,0,0]->[1,2,0]->[0,4,0]->[0,3,1]->etc... The function will be passed a list of integers that can be any length, so func [1,2,0] should result in [0,4,0] being returned.

 

I'm thinking some base cases but for the recursive step I'm having a lot of trouble. It's obviously not right and it's partially pseudo code as I'm not sure how I would actually write it in Haskell. 

 


func (x:xs)

    | x>0 = x-1

    | x>0 head(xs)=head(xs)+length(xs)

    | func xs

 

I just finished up with some Haskell, so I apologize for being on a phone. My typing skills will be limited.

 

But You'd need to be a little more clear on instructions... But since it appears that you're manipulating two values at a time. I'd use a helper value to keep track of index.

 

Funct(lst)

    Helper 1 (lst)

     Where

        Helper i (x:y:ys)

          X>0 = helper i ((x-1):(y+i+1):ys)

          Otherwise = helper (i+1) (y:ys)

 

 

But then case, because when x is the last element, there is no y, and ys is null. So you'd have to create another helper statement for x:ys, knowing you're going to end the statement.

 

I took a class and used it for a whole semester. I'm not a pro, got A-, but can look over my stuff and wrote better on my PC if anything I said made sense.

 

(Also, didn't know if this was a once through type of thing or a complete recursive call)

 

Link to comment
Share on other sites

Link to post
Share on other sites

10 minutes ago, Ryujin2003 said:

I just finished up with some Haskell, so I apologize for being on a phone. My typing skills will be limited.

 

But You'd need to be a little more clear on instructions... But since it appears that you're manipulating two values at a time. I'd use a helper value to keep track of index.

 

Funct(lst)

    Helper 1 (lst)

     Where

        Helper i (x:y:ys)

          X>0 = helper i ((x-1):(y+i+1):ys)

          Otherwise = helper (i+1) (y:ys)

 

 

But then case, because when x is the last element, there is no y, and ys is null. So you'd have to create another helper statement for x:ys, knowing you're going to end the statement.

 

I took a class and used it for a whole semester. I'm not a pro, got A-, but can look over my stuff and wrote better on my PC if anything I said made sense.

 

(Also, didn't know if this was a once through type of thing or a complete recursive call)

 

It's going to be recursive because if I have [0,0,0,0,2,0] then I need to work my way to the 2. ([0,0,0,0,2,0]->[0,0,0,0,1,1]). 

 

And isn't it easier to just grab the length of the list in order to get the index? Since it's recursive I'll always be stripping away the irrelevant initial indices. 

PSU Tier List | CoC

Gaming Build | FreeNAS Server

Spoiler

i5-4690k || Seidon 240m || GTX780 ACX || MSI Z97s SLI Plus || 8GB 2400mhz || 250GB 840 Evo || 1TB WD Blue || H440 (Black/Blue) || Windows 10 Pro || Dell P2414H & BenQ XL2411Z || Ducky Shine Mini || Logitech G502 Proteus Core

Spoiler

FreeNAS 9.3 - Stable || Xeon E3 1230v2 || Supermicro X9SCM-F || 32GB Crucial ECC DDR3 || 3x4TB WD Red (JBOD) || SYBA SI-PEX40064 sata controller || Corsair CX500m || NZXT Source 210.

Link to comment
Share on other sites

Link to post
Share on other sites

39 minutes ago, djdwosk97 said:

It's going to be recursive because if I have [0,0,0,0,2,0] then I need to work my way to the 2. ([0,0,0,0,2,0]->[0,0,0,0,1,1]). 

 

And isn't it easier to just grab the length of the list in order to get the index? Since it's recursive I'll always be stripping away the irrelevant initial indices. 

It could be faster that way yes, but if you have [1,0,0,0,0,0,0,0,2] and you want to be [0,1,0,0,0,0,0,0,2], because it's only making the change at the first int in the list, then it will take unnecessary time to calculate the length and then only change the first two indexes. But, you could do length and then a position counter to make sure your current index isn't going to exceed length+1.

 

That's why I asked what you were doing. I'm not too clear on how it's supposed to function.

Link to comment
Share on other sites

Link to post
Share on other sites

2 minutes ago, Ryujin2003 said:

It could be faster that way yes, but if you have [1,0,0,0,0,0,0,0,2] and you want to be [0,1,0,0,0,0,0,0,2], because it's only making the change at the first int in the list, then it will take unnecessary time to calculate the length and then only change the first two indexes. But, you could do length and then a position counter to make sure your current index isn't going to exceed length+1.

 

That's why I asked what you were doing. I'm not too clear on how it's supposed to function.

[1,0,0,0,0,0,0,2] would become [0,7,0,0,0,0,0,2]. You subtract 1 from the highest non zero element and add the index of the next element+1 to the following index. If you continue the process and keep calling the function you'll eventually end up with [0,0,0,0,0,0,0,0]. 

 

I don't really care about execution time, so I'd rather keep it simpler and just use length (as long as it would work).

PSU Tier List | CoC

Gaming Build | FreeNAS Server

Spoiler

i5-4690k || Seidon 240m || GTX780 ACX || MSI Z97s SLI Plus || 8GB 2400mhz || 250GB 840 Evo || 1TB WD Blue || H440 (Black/Blue) || Windows 10 Pro || Dell P2414H & BenQ XL2411Z || Ducky Shine Mini || Logitech G502 Proteus Core

Spoiler

FreeNAS 9.3 - Stable || Xeon E3 1230v2 || Supermicro X9SCM-F || 32GB Crucial ECC DDR3 || 3x4TB WD Red (JBOD) || SYBA SI-PEX40064 sata controller || Corsair CX500m || NZXT Source 210.

Link to comment
Share on other sites

Link to post
Share on other sites

Just now, djdwosk97 said:

[1,0,0,0,0,0,0,2] would become [0,7,0,0,0,0,0,2]. You subtract 1 from the highest non zero element and add the index of the next element+1 to the following index. If you continue the process and keep calling the function you'll eventually end up with [0,0,0,0,0,0,0,0]. 

 

I don't really care about execution time, so I'd rather keep it simpler and just use length (as long as it would work).

Ok, so you're index 0 is on the right. So get length, and loop while i>0. But in the loop, if you're I'd still look at (x:y;ys) since the way you change variable y is dependent on x >0. If x>0 = funct i ((x-1:y+i:ys)

 

And when x==0, x: funct (i-1) (y:ys)

 

This allows you to keep x at zero, bypass it and recursion continues past that index, while i>0.

Link to comment
Share on other sites

Link to post
Share on other sites

16 minutes ago, Ryujin2003 said:

Ok, so you're index 0 is on the right. So get length, and loop while i>0. But in the loop, if you're I'd still look at (x:y;ys) since the way you change variable y is dependent on x >0. If x>0 = funct i ((x-1:y+i:ys)

 

And when x==0, x: funct (i-1) (y:ys)

 

This allows you to keep x at zero, bypass it and recursion continues past that index, while i>0.

I'm a bit confused by what you're saying.

 

But why couldn't I just recurse down the list until I find a non zero (X>0), subtract 1 from it (X), and then find the length of xs and add that to the head of xs. Shouldn't that work? 

PSU Tier List | CoC

Gaming Build | FreeNAS Server

Spoiler

i5-4690k || Seidon 240m || GTX780 ACX || MSI Z97s SLI Plus || 8GB 2400mhz || 250GB 840 Evo || 1TB WD Blue || H440 (Black/Blue) || Windows 10 Pro || Dell P2414H & BenQ XL2411Z || Ducky Shine Mini || Logitech G502 Proteus Core

Spoiler

FreeNAS 9.3 - Stable || Xeon E3 1230v2 || Supermicro X9SCM-F || 32GB Crucial ECC DDR3 || 3x4TB WD Red (JBOD) || SYBA SI-PEX40064 sata controller || Corsair CX500m || NZXT Source 210.

Link to comment
Share on other sites

Link to post
Share on other sites

18 hours ago, djdwosk97 said:

I'm a bit confused by what you're saying.

 

But why couldn't I just recurse down the list until I find a non zero (X>0), subtract 1 from it (X), and then find the length of xs and add that to the head of xs. Shouldn't that work? 

Either way would work. You can take in a pair X:Y:rest, or individually, x:xs. Doesn't matter. You would still need to make sure you have the empty case in your recursive call. Use the main function to run through all 0 ints and then after finding one you reduce, use a helper to increase the next index value, assuming there is one.

 

Funct (x:xs)

     [] = []

     x==0 = x: funct xs

     Otherwise = (x-1):helper xs

            Where

                 Helper (y:ys)

                    [] =[]

                    Otherwise = (do math here): ys

 

 

If you did:

Funct (list) -- you take in two numbers at a time, and you can case match --

       []=[]

      (0:0:ys) = 0:0: funct ys

      (x:[]) = (x-1):[] --at end of list

      (0:y:ys)= funct y:ys -- first is 0 second is not

      (x:y:ys) =(x-1:y+math:ys)

 

 

 

So you can case match the different possible combinations of zeros, it can make your recursive call easier to handle. This is called pattern matching. I don't have a reference in front of me, on phone again. But there are many ways to skin a cat.

 

You can also use list comprehension to run through and skip all the zeros and do your math on the remainder. It pretty much is what your skill level is at. If doing it for class, they probably don't want you skipping ahead to mechanics not taught yet. If for personal use, choose what makes sense to you.

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×