How to return an array with unhappy numbers removed? - matlab

I'm quite new to using MATLAB, and am still trying to understand how to make this particular function. I understand the formula for performing this on paper, but I'm having trouble translating it into the required MATLAB syntax.
How would a function be written such that it takes an array of numbers, and returns that array with unhappy numbers removed i.e. only happy numbers remaining?
EDIT - Proving and input and output
Input:
array = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37,
41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
Output:
array = [7, 13, 19, 23, 31, 79, 97]
A happy number is such that a number's squared digits summed eventually equal to 1, or continue the process indefinitely as seen here.

I've written a small function (which might be further improved) to test the "happines" of a number.
Current version only works with scalar and one dim. array.
Input: the scalar or array to be tested
Output:
1) an index: happy (1) unhappy(0)
2) the list of happy number within the input set
3) the list of unhappy number within the input set
Running the function with the input specified in the question, the function returns:
function [is_happy,h_array,unh_array]=happy_number(in_val)
%
% Output:
% is_happy: 1 ==> the numberis happy
% 0 ==> the numberis unhappy
% h_array: happy numbers within input
% unh_array: unhappy numbers within input
%
% Input validity check (to be improved)
s=size(in_val);
if(iscell(in_val) || isstr(in_val) || isstruct(in_val) ...
|| ~find(s,1) || length(s) >= 3 || sum(floor(in_val)-in_val) ~= 0)
error('Only scalar or 1 dim array supported')
end
% Vars initialization
h_array=[];
unh_array=[];
h_array_cnt=1;
unh_array_cnt=1;
h_unh_cnt=1;
% Loop through input number
for i=1:length(in_val)
seq=[];
n=in_val(i);
seq_cnt=1;
seq(seq_cnt)=n;
% Test if the number is happy
while(n ~= 1 && n ~= 4)
% Decompose the number in its digits
sn=num2str(n);
nv=str2num(sn(:));
seq_cnt=seq_cnt+1;
seq(seq_cnt)=sum(nv.^2);
n=seq(seq_cnt);
end
% Set and display results
if(n == 1)
disp(['Number ' num2str(seq(1)) ' is HAPPY'])
is_happy(h_unh_cnt)=1;
h_unh_cnt=h_unh_cnt+1;
h_array(h_array_cnt)=seq(1);
h_array_cnt=h_array_cnt+1;
else
disp(['Number ' num2str(seq(1)) ' is UNHAPPY'])
is_happy(h_unh_cnt)=0;
h_unh_cnt=h_unh_cnt+1;
unh_array(unh_array_cnt)=seq(1);
unh_array_cnt=unh_array_cnt+1;
end
end
Hope this helps.

If you have the index of your unhappy numbers. You can remove them by writing :
array(unhappy_index) = [];
If you do not have the unhappy index, you can find them by using the followng command:
find()

Related

Using forall in minizinc with an array set (not contiguous)

I'm trying to use a forall instance to add a constraint but I got this error and I'm not sure which should I do.
(array slice must be contiguous)
in call 'forall'
in array comprehension expression
with i = {10,24}
in binary '<=' operator expression
in call 'slice_1d'
I am working in a schedulling problem, and I need to apply a restriction which determines that a set of tasks (determined by suc) can only starts after a specific task (determined by 1..nTasks) is already finished.
The model follows
include "globals.mzn";
int: n_res;
array [1..n_res] of int: res_cap;
int: n_tasks;
array [1..n_tasks] of int: duration;
array [1..n_res, 1..n_tasks] of int: res_req;
array [1..n_tasks] of set of int: suc;
int: t_max = sum(i in 1..n_tasks)(duration[i]);
array [1..n_tasks] of var 0..t_max: start;
array [1..n_tasks] of var 0..t_max: end;
var 0..t_max: makespan;
% constraint that I can't implement. this constraint should make every task[i] to start after a set of tasks{i} are finished. The set is defined by the array suc.
constraint forall (i in suc)(end[i] <= start[i]);
constraint cumulative(start, duration, row(res_req, 1), res_cap[1]);
constraint cumulative(start, duration, row(res_req, 2), res_cap[2]);
constraint cumulative(start, duration, row(res_req, 3), res_cap[3]);
constraint cumulative(start, duration, row(res_req, 4), res_cap[4]);
constraint forall(i in 1..n_tasks)(end[i] = start[i]+duration[i]);
constraint makespan = max(i in 1..n_tasks)(end[i]);
solve minimize makespan;
The arrays suc and 1..nTasks have the same number of lines.
I have a 1d array with the specific sets of tasks that can start after the task[i] is over.
In a smaller instance, for example:
suc = [{5, 15}, {17, 23, 28}, {10, 12}, {8}]
What i need to implement is:
end[i] | i in 1..nTasks <= start[i] | i in suc
For the specific set that I posted, it could be done manually like this:
end[1] <= start[5]
end[1] <= start[15]
end[2] <= start[17]
end[2] <= start[23]
end[2] <= start[28]
end[3] <= start[10]
end[3] <= start[12]
end[4] <= start[8]
I just start using minizinc and something tells me that I'm missing something that may be simple, however, it's been a while and I can't implement it.
How can I write a forall instance that can do this?
The culprit is this constraint (as the error indicates):
constraint forall (i in suc)(end[i] <= start[i]);
where you trying use suc as a generator for the loop. The problem is that you want two things for this constraint: the start of the current task should be before the successor of that task. And this is not possible using your approach since i will have value such as { 10, 24 }, but there is no value (reference) of the current task (i.e. the value of start[i]).
Here is a way of solving this: Use i in n_res to loop through all the tasks (i is the i'th task), and then loop through suc[i] to get the successors of each task.
constraint forall (i in 1..n_res) (
forall(s in suc[i]) (
end[i] <= start[s]
)
);
Another way, which is perhaps simpler, is to combine the two forall loops into one loop:
constraint forall (i in 1..n_res, s in suc[i]) (
end[i] <= start[s]
);
When I ran the model it generated this solution:
% obj = 51
start = array1d(1..30, [7, 21, 4, 31, 6, 41, 34, 3, 35, 39, 21, 28, 47, 0, 38, 48, 44, 35, 28, 7, 10, 34, 11, 47, 41, 3, 11, 3, 22, 17]);
end = array1d(1..30, [17, 25, 5, 34, 11, 51, 35, 7, 41, 47, 28, 35, 51, 3, 48, 51, 48, 38, 35, 12, 11, 44, 19, 48, 47, 7, 18, 9, 31, 21]);
makespan = 51;
----------
% obj = 51
==========

gnuplot: how to sum over an arbitrary list

For gnuplot, I have a large list of (randomly generated) numbers which I want to use as indices in a sum. How do I do it?
Here is what I mean. Let's say the list of numbers is
list = [81, 37, 53, 22, 72, 74, 44, 46, 96, 27]
I have a function
f(x,n) = cos(n*x)
I now want to plot the function, on the interval (-pi,pi) which is the sum of the f(x,n) as n runs through the numbers in list.
If you can control how your list looks like, try the following:
num = 10
# Let the numbers be in a space separated string.
# We can access the individual numbers with the word(string, index) function.
list = "81 37 53 22 72 74 44 46 96 27"
f(x,n) = cos(n*x)
set terminal pngcairo
set output "sum_cos.png"
set xrange [-pi:pi]
set samples 1000
# Build the plot command as a macro.
plt_cmd = ""
do for [n=1:num] {
plt_cmd = sprintf("%s + f(x,%s)", plt_cmd, word(list,n))
}
# Check what we have done so far.
print plt_cmd
titlestring = "{/Symbol S} cos(n_i*x), i = 1 ...".num
# Finally plot the sum by evaluating the macro.
plot #plt_cmd title titlestring
This is the result:

Increment variable for if statement

Is there a more elegant way to write this? I dont want to use a for loop
if i==1 || i==6 || i==11 || i==16 || i==21 || i==26 || i==31 || i==36
function
end
basically i is the index of a vector, after each fifth element of this vector (starting with the first ) a specific function is applied. i starts with 1 and it increments after the if statement and just if it equals these values of the if condition the if statement is valid
EDITTED FOR MATLAB CODE OF MODULO
output = mod(input, 5); //this will output 1 if it is 1, 5, 11, 16
//input is your 1, 5, 11, 16 etc
//output is the result of modulo. else it is 0, 2, 3, 4
if(output == 1)
[previous answer]
i forgot how to write this in matlab but with your values, put it this way.
if(number%5==1)
any input 1 or 6 or 11 or any else that can add 5 to it, you'll end up in 1. else it will return false

Palindromic Wing Primes - Mathematica

definition :
Palindromic Wing Primes (or PWP's for short) are numbers that
are primes, palindromic in base 10, and consisting of one central digit
surrounded by two wings having an equal amount of identical digits and
different from the central one. E.g.
101
99999199999
333333313333333
7777777777772777777777777
11111111111111111111111111111111411111111111111111111111111111111
A number is a palindromic wing prime if it is both a palindromic wing and prime. Here are the first several palindromic wing primes:
101, 131, 151, 181, 191, 313, 353, 373, 383, 727, 757, 787, 797, 919, 929, 11311, 11411, 33533, 77377, 77477, 77977, 1114111, 1117111, 3331333, 3337333, 7772777, 7774777, 7778777, 111181111, 111191111, 777767777, 77777677777,...
Please i need help with find the right algorithm or pseudo code for if a number is palindromic wing
and if someone could help me with guid me to more info about the Palindromic Wing Primes , their history and the last results and maybe help me with "mathematica Programming " that would be amazing
kind regards
Testing wing palindromes from wing length 1 to 20 using Mathematica.
sets = DeleteCases[Tuples[Range[0, 9], 2], {a_, a_} | {0, _}];
grow[n_] := Map[Flatten, {a = ConstantArray[#1, n], #2, a} & ### sets]
test[c_] := If[PrimeQ[k = FromDigits#c], AppendTo[output, k]]
run[from_, to_] := Do[test /# grow[i], {i, from, to}]
output = {};
run[1, 20]
101
131
151
181
191
...
111111111111111111131111111111111111111
777777777777777777797777777777777777777
77777777777777777777977777777777777777777
Interesting definition, first time that I hear about that.
Assuming that you know how to check if a number is palindromic and prime, here is some pseudo and python code
isPalindromicWing(N){
if isPalindromic(N){
num <- toString(N)
tam <- length(num)
if isOdd(tam) and lenght(toSet(num)) = 2{
middle <- num[ floor(tam/2) ]
if 1 = num.count(middle){
return True
}
}
}
return False
}
isPWP(N){
return isPalindromicWing(N) and isPrime(N)
}
I use sets to remove repetitions, and as the number can only have 2 different digit with lenght(toSet(num)) == 2 I check for that, then I take the middle number and check if only there is one of it in the number. The rest I think is self explanatory.
in python that is
def isPalindromic(N):
num = str(N)
return N == int( num[::-1] )
def isPalindromicWing(n):
if isPalindromic(n):
num = str(n)
tam = len(num)
if tam % 2 == 1 and len(set(num)) == 2:
middle = num[tam // 2]
if 1 == num.count(middle):
return True
return False
I don't know about "mathematica Programming", but is you understand this code surely you can do it in that too

fprintf print chars and num with no loops

I'm trying to use fprintf to write a data file. Say I have a matrix containing data like this:
Values = [ 1, 735123.0, 23, 24, 25;
2, 735123.5, 34, 35, 36;
...
8000, 739122.5, 21, 22, 43]
I can write that to a file using:
fprintf(FileID, '%d, %f, %d, %d, %d', Values')
But really that second column represents dates (datestr(735123.5) = 11-Sep-2012 12:00:00) and I'd like fprintf to print dates in the second column of the data file, so that the file will read
1, 11-Sep-2012 00:00:00, 23, 24, 25
2, 11-Sep-2012 12:00:00, 34, 35, 36
...
8000, 24-Aug-2023 12:00:00, 21, 22, 43
My matrix is thousands of lines long so I'd prefer not to have to loop through line by line.
Any suggestions how to procede?
Something like
n = num2cell(Values');
n(2,:) = cellfun(#datestr, n(2, :),'UniformOutput', false);
fprintf(FileID, '%d, %s, %d, %d, %d', n{:});
Although cellfun is basically a loop.
Without for loops or cellfun:
separator = repmat(', ',size(Values,1),1); %// column used as separator
lineFeeds = repmat('\n',size(Values,1),1); %// column of line feeds
string = [ num2str((Values(:,1))) ...
separator ...
datestr(Values(:,2)) ...
separator ...
num2str(Values(:,3)) ...
separator ...
num2str(Values(:,4)) ...
separator ...
num2str(Values(:,5)) ...
lineFeeds ];
string = reshape(string.',1,[]); %'// put everything in one row
FileID = fopen('tmp.txt', 'wt'); %// use 't', or '\n' may not get written to file
fprintf(FileID, string);
fclose(FileID);