I need to change array(1,0,2,3,4,0,0,5,6,0,7) with array(1,1,2,3,4,4,4,5,6,6,7).
My code:
select
arrayMap (i-> (if(i=0, indexOf(arr,i)-1, i)), arr)
from (select array(1,0,2,3,4,0,0,5,6,0,7) as arr)
But it returns array(1,1,2,3,4,1,1,5,6,1,7). How to do it?
It looks like pretty weird but works (remark: zero-indexed 0-value be ignored):
SELECT
arrayEnumerate(arr) AS indexes,
[0, 1, 0, 2, 0, 0, 0, 3, 4, 0, 0, 5, 6, 0, 7, 8, 0] AS arr,
arrayMap(i -> if((arr[i] = 0) AND (i > 1), arr[(i - arrayFirst(x -> (arr[(i - x)] != 0), indexes))], arr[i]), indexes) AS result
FORMAT Vertical
Result:
Row 1:
──────
indexes: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]
sourceData: [0,1,0,2,0,0,0,3,4,0,0,5,6,0,7,8,0]
result: [0,1,1,2,2,2,2,3,4,4,4,5,6,6,7,8,8]
Given a list of positive integers and a target value, generate a solution set. For example, if the list is [10, 1, 2, 7, 6, 1, 5] and the target is 8, the solution set is...
[
[1, 7],
[1, 2, 5],
[2, 6]
[1, 1, 6]
[
I know there a multiple solutions to this, such as dp, but I am trying to get my dfs solution working and I believe I am very close, but I simply cannot get the correct result. If possible, I would like it if you didn't change my initial answer too much, if that's not possible, any solution will do.
def combinationSum(self, candidates, target):
candidates.sort()
total = []
self.helper(candidates, 0, target, [], total)
def helper(self, candidates, curr, target, temp, total):
if target == 0:
total.append(temp)
return
if target < 0:
return
for i in range(curr, len(candidates)):
# avoid duplicates
if i > curr and candidates[i] == candidates[i-1]:
continue
temp.append(candidates[i])
self.helper(candidates, i+1, target-candidates[i], temp, total)
# I'm not sure what to do here
This obviously does not give me the right result but I do think I am on the right track towards generating the solution set. I simply do not understand what I need to do after the recursive call to remove unnecessary elements.
I think this is along the lines of what you are trying to do:
def solve(target, sum, candidates, answer):
if sum == target:
print answer
return
if len(candidates) == 0 or sum > target:
return
first = candidates[0]
count = candidates.count(first);
answer.append(first)
solve(target, sum+first, candidates[1:], answer) #using the current number
answer.pop()
solve(target, sum, candidates[count:], answer) #skipping the current number and any duplicates
if __name__ == "__main__":
candidates = [10, 1, 2, 7, 6, 1, 5]
candidates.sort();
solve(8, 0, candidates, [])
The key point is that solve has two recursive calls.
The first recursive call uses the first number in the candidates list. So it
appends the first number to the answer
adds the first number to the sum
removes only the first number from the candidates list that is
passed to the next level
The second recursive call doesn't use the first number in the candidates list. And since it doesn't use the first number, it also doesn't use any duplicates of the first number. That's the reason for the count variable. candidates.count(first) is the number of entries in the list that are equal to first. So in the recursive call candidates[count:] removes the first element and any duplicates. (This assumes that the list is sorted, which should be done once before calling solve).
Here's one possible solution using recursion – I chose a tuple to represent the combinations, but you could've used list for those too
def combinationSum (l, target, sum = 0, comb = ()):
# base case: empty input [l]
if not l:
return []
# inductive case: [l] has at least one element
else:
# [x] is the first sub-problem
# [xs] is the rest of the sub-problems
x, *xs = l
# [x] plus [sum] is bigger than [target]
if x + sum > target:
return \
combinationSum (xs, target, sum, comb)
# [x] plus [sum] is smaller than [target]
elif x + sum < target:
return \
combinationSum (xs, target, sum + x, (x, *comb)) + \
combinationSum (xs, target, sum, comb)
# [x] plus [sum] is equal to [target]
else:
return \
[ (x, *comb) ] + \
combinationSum (xs, target, sum + x, (x, *comb)) + \
combinationSum (xs, target, sum, comb)
data = [10, 1, 2, 7, 6, 1, 5]
print (combinationSum (data, 8))
# [(5, 2, 1), (7, 1), (1, 6, 1), (6, 2), (5, 1, 2), (1, 7)]
If you want combinationSum to allow for duplicate values, you only have to change one part. Note, the program considers eg (5, 1, 1, 1) a solution 3 times because the 1 appears in 3 unique positions. If you only wanted (5, 1, 1, 1) to appear once, you'd have to consider a different approach.
...
elif x + sum < target:
return \
combinationSum (xs, target, sum + x, (x, *comb)) + \
combinationSum (l , target, sum + x, (x, *comb)) + \
combinationSum (xs, target, sum, comb)
...
print (combinationSum (data, 8))
# [ (1, 1, 1, 1, 1, 1, 1, 1)
# , (1, 1, 1, 1, 1, 1, 1, 1)
# , (2, 1, 1, 1, 1, 1, 1)
# , (1, 1, 1, 1, 1, 1, 1, 1)
# , (1, 2, 1, 1, 1, 1, 1)
# , (1, 1, 1, 1, 1, 1, 1, 1)
# , (2, 2, 1, 1, 1, 1)
# , (1, 1, 2, 1, 1, 1, 1)
# , (1, 1, 1, 1, 1, 1, 1, 1)
# , (1, 2, 2, 1, 1, 1)
# , (1, 1, 1, 2, 1, 1, 1)
# , (1, 1, 1, 1, 1, 1, 1, 1)
# , (5, 1, 1, 1)
# , (2, 2, 2, 1, 1)
# , (1, 1, 2, 2, 1, 1)
# , (1, 1, 1, 1, 2, 1, 1)
# , (6, 1, 1)
# , (1, 1, 1, 1, 1, 1, 1, 1)
# , (5, 1, 1, 1)
# , (1, 2, 2, 2, 1)
# , (1, 1, 1, 2, 2, 1)
# , (1, 1, 1, 1, 1, 2, 1)
# , (5, 2, 1)
# , (7, 1)
# , (1, 6, 1)
# , (1, 1, 1, 1, 1, 1, 1, 1)
# , (5, 1, 1, 1)
# , (2, 2, 2, 2)
# , (1, 1, 2, 2, 2)
# , (1, 1, 1, 1, 2, 2)
# , (6, 2)
# , (1, 1, 1, 1, 1, 1, 2)
# , (5, 1, 2)
# , (1, 7)
# , (1, 1, 6)
# , (1, 1, 1, 1, 1, 1, 1, 1)
# , (5, 1, 1, 1)]
# ]
I want to find all solutions for this "For a given interval of years to get the number of days per week(mon, tue, web,...,sun) of the year"
does anybody know other answer? share it please ;)
this is my query:)
WITH dat AS
(SELECT &&start_year + level - 1 cur_year, DECODE(MOD(&start_year + level - 1, 4), 0, 0, 1) no_leap,
TO_NUMBER(TO_CHAR(TO_DATE('01.01.'||TO_CHAR(&start_year + level - 1)), 'D')) d
FROM dual
CONNECT BY LEVEL < &end_year - &start_year + 2)
SELECT cur_year,
51 + DECODE(no_leap, 1, DECODE(d, 1, 2, 1), DECODE(d, 1, 2, 7, 2, 1)) mon,
51 + DECODE(no_leap, 1, DECODE(d, 2, 2, 1), DECODE(d, 2, 2, 1, 2, 1)) tue,
51 + DECODE(no_leap, 1, DECODE(d, 3, 2, 1), DECODE(d, 3, 2, 2, 2, 1)) wed,
51 + DECODE(no_leap, 1, DECODE(d, 4, 2, 1), DECODE(d, 4, 2, 3, 2, 1)) thu,
51 + DECODE(no_leap, 1, DECODE(d, 5, 2, 1), DECODE(d, 5, 2, 4, 2, 1)) fri,
51 + DECODE(no_leap, 1, DECODE(d, 6, 2, 1), DECODE(d, 6, 2, 5, 2, 1)) sat,
51 + DECODE(no_leap, 1, DECODE(d, 7, 2, 1), DECODE(d, 7, 2, 6, 2, 1)) sun
FROM dat;
You should be taking advantage of Oracle's date-arithmetic. When you minus two dates from each other a number is returned, the number of days between the two dates. If there's not an integer difference then the actual difference is returned:
SQL> select sysdate - to_date('20120504 15', 'yyyymmdd hh24') from dual;
SYSDATE-TO_DATE('2012050415','YYYYMMDDHH24')
--------------------------------------------
3.76489583
Please note that this does not include timestamp, only date data-types. Doing timestamp arithmetic returns an interval data-type.
Most of a solution would be
with dates as (
select to_char(to_date('&start_year','yyyy') + level, 'fmDAY') as days
from dual
connect by level < to_date('&end_year','yyyy') - to_date('&start_year','yyyy')
)
select ...
Note the fm modifier of the format model; this removes trailing spaces.
As a general rule, when dealing with dates it is always preferable to use dates, rather than numbers or characters. Your connect by clause CONNECT BY LEVEL < &end_year - &start_year + 2, though simple has caused you to do a lot of extra work in order to get your solution to work.
Let's say I have the following input in apache pig:
(123, ( (1, 2), (3, 4) ) )
(666, ( (8, 9), (10, 11), (3, 4) ) )
and I want to convert these 2 rows into the following 7 rows:
(123, (1, 2) )
(123, (3, 4) )
(666, (8, 9) )
(666, (10, 11) )
(666, (3, 4) )
i.e. this is sorta 'doing the opposite of a GROUP'. Is this possible in pig latin?
Take a look at FLATTEN. It does what you probably need.
However, using your notation above, it looks like the list of tuples is a tuple. This should be a bag for this to work properly.
Instead of:
(123, ( (1, 2), (3, 4) ) )
(666, ( (8, 9), (10, 11), (3, 4) ) )
You should be representing your data as:
(123, { (1, 2), (3, 4) } )
(666, { (8, 9), (10, 11), (3, 4) } )
Then, once it is this form, you can do:
O = FOREACH grouped GENERATE $0, FLATTEN($1);