I am trying to create a recursive multiplier in ruby.
#j = 0
def multiplier(x, y, z)
count = 0
if x > 0
if z > 0
#j += y
z -= 1
count += 1
multiplier(x, y, z)
else
x -= 1
z = count
p z
multiplier(x, y, z)
end
else
return #j
end
end
def main
puts "Calculation is: " + multiplier(3, 10, 4).to_s
end
main
X is how many times the multiplication happens
Y is the number we want to multiply
Z is the number we multiply by
The code should output 120 with the variables that are there
I am having issues getting Z to stay what I need it to be. Also, I'd prefer to do this without a global variable
So something like x*(y*z) but without the times symbol
The main issue with your code is count is a local variable, it is not saved between recursive calls. Also, if you want to avoid globals, pass the variable as an additional parameter in call to the function. In FP we call it accumulator:
def multiplier(x, y, z, j = 0)
if z > 0
multiplier(x, y, z - 1, j + y)
elsif z.zero? # done with z, jump to x × (y × z)
# z = -1 to explicitly mark we are done with z
multiplier(x, j, -1, 0)
elsif y.zero? # yay, we are all set, reducing is done!
j
else
# still doing x × result step
multiplier(x, y - 1, -1, j + x)
end
end
multiplier(3, 10, 4)
#⇒ 120
The above surely lacks necessary checks for input validity, but I bet you got the idea.
Building on the recursive answer above, here's a more generic function that can take an arbitrarily long list of positive integers and multiply them by recursive addition:
def multiplier(*integers, accum: 0)
if integers.size == 1
# We are finished!
integers[0]
elsif integers[-1].positive?
# "Multiply" the last two integers, by recursive addition
integers[-1] -= 1
multiplier(*integers, accum: accum + integers[-2])
else
# The above multiplication is complete; set the last integer to its result
integers[-2] = accum
multiplier(*integers[0..-2])
end
end
I would say the idiomatic way in ruby is using iterators instead of recursion/cycles
def multiplier(x, y, z)
x.times.map do
y.times.map do
z
end.reduce(:+)
end.reduce(:+)
end
or
def multiplier(x, y, z)
x.times.map do
y.times.map do
z
end
end.flatten.reduce(:+)
end
Or if the only operation is inc
def multiplier(x, y, z)
j = 0
x.times do
y.times do
z.times do
j += 1
end
end
end
j
end
the output is the same
multiplier(3, 10, 4)
# 120
For an arbitrary number of args we have to use recursion
def multiplier(*xs, res: 0)
return res if xs.empty?
xs[0].times do
res += 1 if xs.size == 1
res = multiplier(*xs.drop(1), res: res)
end
res
end
or
def multiplier(*xs, res: 0)
head, *tail = xs
head.to_i.times do
res += 1 if tail.empty?
res = multiplier(*tail, res: res)
end
res
end
I'd start by writing a method to multiply two numbers recursively:
def multiply_2(a, b)
return 0 if a.zero?
b + multiply_2(a - 1, b)
end
multiply_2(3, 4)
#=> 12
and build upon that method to multiply three numbers:
def multiply_3(a, b, c)
multiply_2(multiply_2(a, b), c)
end
multiply_3(3, 4, 10)
#=> 3
and eventually extend that to handle n numbers:
def multiply_n(a, b, *more)
result = multiply_2(a, b)
return result if more.empty?
multiply_n(result, *more)
end
multiply_n(3, 4, 10, 2)
#=> 240
Note that you might run into a SystemStackError for large numbers. This can be avoided by making multiply_2 tail-recursive (leaving that as an exercise, it's not hard) and enabling Ruby's :tailcall_optimization.
It could be written thusly.
def multiplier(*args)
prod = recurse(*args.map(&:abs))
args.count { |n| n < 0 }.even? ? prod : -prod
end
def recurse(first, *rest)
first.zero? || rest.empty? ? first : ([recurse(*rest)]*first).sum
end
multiplier(3, 10, 4) #=> 120
multiplier(3, 10, 4, 2, 3) #=> 720
multiplier(3, -10, 4) #=> -120
multiplier(3, -10, -4) #=> 120
multiplier(3, 0, 4) #=> 0
multiplier(3, 0, -4) #=> 0
Suppose we wish to compute multiplier(3, -4). recurse(3, 4) is called, where
first = 3
rest = [4]
first.zero? #=> false
rest.empty? #=> false
so we compute
([recurse(4)]*3).sum
In recurse(4),
first = 4
rest = []
As rest.empty #=> true, recurse returns first #=> 4, so
([recurse(4)]*3).sum]
#=> ([4]*3).sum => [4,4,4].sum => 12
is returned to multiplier. As [3, -4] contains an odd number of negative values, multiplier returns -12.
I am having a small issue sending https though ajax would anyone be able to look at the code below and let me know weather I am doing something wrong.
$(function(){
$('form').submit(function() {
Username = $("input[name=Username]").val();
AccountCode = $("input[name=AccountCode]").val();
MerchantNumber = $("input[name=MerchantNumber]").val();
CustomerNumber = $("input[name=CustomerNumber]").val();
vPassword = $("input[name=Password]").val();
md5 = $.md5(AccountCode+Username+MerchantNumber+CustomerNumber+vPassword);
//MD5[AccountCode+Username+MerchantNumber+CustomerNumber+vPassword]
//alert(md5);
checkout($(this).serialize()+"&password="+md5);
return false;
});
});
function checkout(formstring){
$.ajax({
type: 'POST',
url: "https://services.incard.com.au/processpayment.ashx",
data: formstring,
dataType: 'json',
contentType: "application/x-www-form-urlencoded;charset=utf-8",
beforeSend: function() {
switch (e) {
case 3:
//alert("jajka");
break;
}
},
success: function(data){alert(data);},
error:function(data){alert(data);}
});
return false;
}
/*
* jQuery MD5 Plugin 1.2.1
* https://github.com/blueimp/jQuery-MD5
*
* Copyright 2010, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://creativecommons.org/licenses/MIT/
*
* Based on
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for more info.
*/
/*jslint bitwise: true */
/*global unescape, jQuery */
(function ($) {
'use strict';
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y) {
var lsw = (x & 0xFFFF) + (y & 0xFFFF),
msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function bit_rol(num, cnt) {
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* These functions implement the four basic operations the algorithm uses.
*/
function md5_cmn(q, a, b, x, s, t) {
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
}
function md5_ff(a, b, c, d, x, s, t) {
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function md5_gg(a, b, c, d, x, s, t) {
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function md5_hh(a, b, c, d, x, s, t) {
return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5_ii(a, b, c, d, x, s, t) {
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}
/*
* Calculate the MD5 of an array of little-endian words, and a bit length.
*/
function binl_md5(x, len) {
/* append padding */
x[len >> 5] |= 0x80 << ((len) % 32);
x[(((len + 64) >>> 9) << 4) + 14] = len;
var i, olda, oldb, oldc, oldd,
a = 1732584193,
b = -271733879,
c = -1732584194,
d = 271733878;
for (i = 0; i < x.length; i += 16) {
olda = a;
oldb = b;
oldc = c;
oldd = d;
a = md5_ff(a, b, c, d, x[i], 7, -680876936);
d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
b = md5_gg(b, c, d, a, x[i], 20, -373897302);
a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);
d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
d = md5_hh(d, a, b, c, x[i], 11, -358537222);
c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
a = md5_ii(a, b, c, d, x[i], 6, -198630844);
d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
}
return [a, b, c, d];
}
/*
* Convert an array of little-endian words to a string
*/
function binl2rstr(input) {
var i,
output = '';
for (i = 0; i < input.length * 32; i += 8) {
output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
}
return output;
}
/*
* Convert a raw string to an array of little-endian words
* Characters >255 have their high-byte silently ignored.
*/
function rstr2binl(input) {
var i,
output = [];
output[(input.length >> 2) - 1] = undefined;
for (i = 0; i < output.length; i += 1) {
output[i] = 0;
}
for (i = 0; i < input.length * 8; i += 8) {
output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32);
}
return output;
}
/*
* Calculate the MD5 of a raw string
*/
function rstr_md5(s) {
return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
}
/*
* Calculate the HMAC-MD5, of a key and some data (raw strings)
*/
function rstr_hmac_md5(key, data) {
var i,
bkey = rstr2binl(key),
ipad = [],
opad = [],
hash;
ipad[15] = opad[15] = undefined;
if (bkey.length > 16) {
bkey = binl_md5(bkey, key.length * 8);
}
for (i = 0; i < 16; i += 1) {
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
}
/*
* Convert a raw string to a hex string
*/
function rstr2hex(input) {
var hex_tab = '0123456789abcdef',
output = '',
x,
i;
for (i = 0; i < input.length; i += 1) {
x = input.charCodeAt(i);
output += hex_tab.charAt((x >>> 4) & 0x0F) +
hex_tab.charAt(x & 0x0F);
}
return output;
}
/*
* Encode a string as utf-8
*/
function str2rstr_utf8(input) {
return unescape(encodeURIComponent(input));
}
/*
* Take string arguments and return either raw or hex encoded strings
*/
function raw_md5(s) {
return rstr_md5(str2rstr_utf8(s));
}
function hex_md5(s) {
return rstr2hex(raw_md5(s));
}
function raw_hmac_md5(k, d) {
return rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d));
}
function hex_hmac_md5(k, d) {
return rstr2hex(raw_hmac_md5(k, d));
}
$.md5 = function (string, key, raw) {
if (!key) {
if (!raw) {
return hex_md5(string);
} else {
return raw_md5(string);
}
}
if (!raw) {
return hex_hmac_md5(key, string);
} else {
return raw_hmac_md5(key, string);
}
};
}(typeof jQuery === 'function' ? jQuery : this));
In your checkout function, e is not defined. As soon as this ReferenceError occurs, it prevents the form callback from returning false, which allows the form to submit normally and redirects the page.
The entire code block:
beforeSend: function() {
switch (e) {
case 3:
//alert("jajka");
break;
}
},
doesn't do anything at all - just delete that, and the AJAX call will be executed when the form is submitted.
However, you'll now probably run into a separate issue - your comments suggest that the page with this snippet of code is not on the same subdomain (or protocol) as the AJAX request you're trying to complete. Due to the same origin policy, browsers won't allow AJAX requests to different domains, protocols or ports. You'll have to find a way to host the resource on the same domain and protocol to use this code.
(Alternatively, you could use JSONP, although it looks like you're processing a payment here - not the best idea to use a GET request!)