I am able to hide my text inside an Image. But when I tried to extract the text from my image, I always only able manage to get only the first character. I don't know where went wrong?
My embed operation code:
public static Bitmap embedMessage(string hiddenText, Bitmap oriImage)
{
Color currentPixel;
int[] colorRGB = new int[3];
List<int> messageValue = new List<int>();
messageValue = ConvertMessage(messageValue, hiddenText);
int messageIndex = messageValue.Count;
int binaryCount = 0;
int zeroAdded = 0;
for(int row = 0; row < oriImage.Height; row++)
{
for(int col = 0; col < oriImage.Width; col++)
{
currentPixel = oriImage.GetPixel(col, row);
colorRGB[0] = ConvertEven(currentPixel.R);
colorRGB[1] = ConvertEven(currentPixel.G);
colorRGB[2] = ConvertEven(currentPixel.B);
for(int rgbIndex = 0; rgbIndex < colorRGB.Length; rgbIndex++)
{
if(messageIndex > 0)
{
colorRGB[rgbIndex] += messageValue[messageValue.Count - messageIndex] % 2;
messageValue[messageValue.Count - messageIndex] /= 2;
}
}
if (messageIndex == 0 && zeroAdded < 8)
{
oriImage.SetPixel(col, row, Color.FromArgb(colorRGB[0], colorRGB[1], colorRGB[2]));
zeroAdded++;
Console.WriteLine("Adding zero number: " + zeroAdded);
}
else
{
Console.WriteLine("Set Pixel");
oriImage.SetPixel(col, row, Color.FromArgb(colorRGB[0], colorRGB[1], colorRGB[2]));
}
if (zeroAdded == 8)
{
Console.WriteLine("Final Pixel Add");
oriImage.SetPixel(col, row, Color.FromArgb(colorRGB[0], colorRGB[1], colorRGB[2]));
return oriImage;
}
binaryCount++;
if (binaryCount % 8 == 0) { messageIndex--; Console.WriteLine("Message Index deducted"); }
}
}
return oriImage;
}
My embed implementation is the same to this example As for extraction I used the exact extraction code from the example. No matter what I tried, I am still only getting the first character of my embedded text. I tried checking my code by printing each operations and all of them fires without any issue which means the embed operation should be working as expected.
Just found my problem. Everything in my embed method should be in the R G B for loop.
Related
I was doing a coding test (for practice) that went something like this:
Input is a string with |'s and *'s.
E.g. **|*|*|**|***
Implement the function:
List<int> countItems(string line, List<int> startLocations, List<int> endLocations)
Count the number of * characters that are between an opening and closing pair of | characters.
Where the 2 locations are arrays with the start and end locations (indices) to consider withing the string line.
For example if line = *|*|* and startLocations = [1] and endLocations = [3] it means
I need to check the substring *|*.
And since there is only 1 pipe, the result is zero.
The location values seemed to be 1-based and not 0-based for some reason.
If the range was 1 and 5, for example, the result would be 1 because there is only 1 * between pipes.
The code I came up with that did manage to solve about half the test cases is as follows:
List<int> countItems(string line, List<int> startLocations, List<int> endLocations)
{
var results = new List<int>();
if (String.IsNullOrWhiteSpace(line) || startLocations.Count == 0)
{
return results;
}
for (var i = 0; i < startLocations.Count; i++)
{
var startIndex = startLocations[i] - 1;
var endIndex = endLocations[i] - 1;
var start = false;
var total = 0;
var tempTotal = 0;
for (var j = startIndex; j < endIndex; j++)
{
if (!start && line[j] == '|')
{
start = true;
tempTotal = 0;
}
else if (start && line[j] == '*')
{
tempTotal++;
}
else if (line[j] == '|')
{
total += tempTotal;
tempTotal = 0;
}
}
if (line[endIndex] == '|')
{
total += tempTotal;
}
results.Add(total);
}
return results;
}
All the test cases either passed or failed because it ran out of time.
The error said it exceeded a time of 3 seconds.
Now I couldn't see the actual data being passed into the tests, so I'm not able to test it more.
But I suspect the solution was some kind of temporary list or dictionary so as to only iterate over the string 1 time instead of many times as in my code.
I want to learn what kind of solution to use in cases like this, but not really sure if this is a common type of question where the solution has some kind of name or common concept.
I would appreciate any obvious pointers to solving this type of question or even links to similar programming challenges where I can practice more.
In this case I think the best option would be to use stack theory.
It is a variation of the parenthesis balancing problem. You can find more about it here
Article parenthesis balancing problem
I managed to redo the test and I found the answer and problem type.
This is a "plates between candles" type of problem.
I was trying to solve it myself but almost ran out of time and eventually just copy/pasted an answer I found.
This was a practice run, not an actual test or application.
This was the solution that worked... I'll be studying it to better understand it...
List<int> numberOfItems(string s, List<int> startIndices, List<int> endIndices)
{
int q = startIndices.Count;
int l = s.Length;
for (var i = 0; i < startIndices.Count; i++)
{
startIndices[i]--;
endIndices[i]--;
}
var ans = new List<int>();
var prev = new int[l];
var next = new int[l];
var preSum = new int[l];
int p = -1, nxt = -1;
// calculating prev candle up to this index.
for (int i = 0; i < l; i++)
{
if (s[i] == '|')
{
p = i;
}
prev[i] = p;
}
//Calculating next candle from this index.
for (int i = l - 1; i >= 0; i--)
{
if (s[i] == '|')
{
nxt = i;
}
next[i] = nxt;
}
int c = 0;
// calculating the number of stars between these indices.
for (int i = 0; i < l; i++)
{
if (s[i] == '*')
{
c++;
}
preSum[i] = c;
}
// calculating ans.
for (int k = 0; k < q; k++)
{
int i = startIndices[k];
int j = endIndices[k];
int right = prev[j];// position of left candle.
int left = next[i];// position of right candle.
//cout<<right<<left;
if (left == -1 || right == -1 || left > right)
{
ans.Add(0);
}
else
{
ans.Add(preSum[right] - preSum[left]);
}
}
return ans;
}
I need to display a Sheet so that the lines are aligned bottom and left. If there are no 10 characters in the word, the number of "+" characters is added so that the total of the line is 10 characters (see my output).
Why, when I print a List, I lose one row?
What's wrong with my piece of code? This matrix should be 10X10.
My output
List<string> filtredList = new List<string>() { "Jacuzzi", "Action", "Chinchilla", "Squeezebox", "Academic", "Abstract" };
int row = 10;
filtredList = Sorting(filtredList); //method is sorting by descending.
foreach (var item in filtredList) Console.WriteLine("Item: " + item + " length: " + item.Length);
Console.WriteLine("-------------------------------------");
//AFTER SORTING IN LIST:
//1)Squeezebox 2)Chinchilla 3)Academic 4)Abstract 5)Jacuzzi 6)Action
for (int i = 10; i > 0; i--)
{
try
{
if (filtredList[i].Length != 10)
{
Console.Write(filtredList[i]);
row = 10 - filtredList[i].Length;
Console.WriteLine(string.Concat(Enumerable.Repeat("+", row)));
}
else Console.WriteLine(filtredList[i]);
}
catch (SystemException)
{
row = 10;
Console.WriteLine(string.Concat(Enumerable.Repeat("+", row)));
}
}
Because your for loop is never gets to 0:
for (int i = 10; i > 0; i--)
i goes from 10 to 1 and that's why the first item of your list never prints.
Note:
Index of first item of an array or a list is 0
The better code would be:
for (int i = 9; i >= 0; i--)
Although you can use better alternatives for some of your code, but this will solve your problem.
EDIT:
You can use this approach (just change the for part to this) to not raise any exceptions (because its not normally a use case for try-catch)and also get faster results:
for (int i = 9; i >= 0; i--)
{
if (i < filtredList.Count)
{
if (filtredList[i].Length != 10)
{
Console.Write(filtredList[i]);
row = 10 - filtredList[i].Length;
Console.WriteLine(new string('+', row));
}
else Console.WriteLine(filtredList[i]);
}
else
{
row = 10;
Console.WriteLine(new string('+', row));
}
}
I am trying to save some information from textbox controls that have been dynamically created and may have been deleted since their creation. I can provide an array of strings that match a number already being used to save that data to match my list of deleted against. essentially to prevent exceptions from being thrown I need to not try and save data from the deleted textboxes. Here is what I am working with atm:
int TextboxNumber = 0;
for (int pc = 0; pc < Int32.Parse(PrinterCount.Text); pc++)
{
for (int r = 0; r <= 2; r++)
{
TextboxNumber = pc * 3 + r;
if (TextboxNumber != Int32.Parse(deleted[]))
{
TextboxName = "textBox" + TextboxNumber.ToString();
printerinfo = printerinfo + this.Controls[TextboxName].Text + ",";
}
}
using (StreamWriter w = File.AppendText(path))
{
w.WriteLine(printerinfo);
};
printerinfo = "";
}
You can see on Line 6 is where I have this if statement. The deleted[] array can be any series of three numbers such as 0,1,3 or 7,8,9 , or both or more... How would one validate in this situation?
This is the answer for any who come after; on line 6 put
if (checkdeleted(TextboxNumber))
then create this function
bool checkdeleted(int number)
{
string[] deleted = Deleted.Text.Split(',');
if (deleted.Count() != 1)
{
for (int c = deleted.Count() - 2; c >= 0; c--)
{
if (Int32.Parse(deleted[c]) == number)
{
return false;
}
}
}
return true;
}
Thank you very much me!
this is the program I'm trying to write:
Write a program that reads a text and line width from the console. The program should distribute the text so that it fits in a table with a specific line width. Each cell should contain only 1 character. It should then read a line with numbers, holding the columns that should be bombarded.
My code looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _04.Text_Bombardment
{
class Program
{
static void Main(string[] args)
{
var sentence = Console.ReadLine();
var bombing = int.Parse(Console.ReadLine());
var selected = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
Dictionary<int, bool> bombDict = new Dictionary<int, bool>();
var newSentence = sentence + new string(' ', bombing - sentence.Length % bombing); // whole row minus words left
for (int i = 0; i < selected.Length; i++)
{
bombDict.Add(selected[i], true);
}
var rows = newSentence.Length / bombing;
var cols = bombing;
var count = 0;
var arrSent = newSentence.ToCharArray();
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
if (bombDict.ContainsKey(j) && bombDict[j] == true && arrSent[count] != ' ')
{
arrSent[count] = ' ';
try
{
if (arrSent[count + bombing] == ' ')
{
bombDict[j] = false;
}
else
{
bombDict[j] = true;
}
}
catch (IndexOutOfRangeException)
{
continue;
}
}
count++;
}
}
var finalSent = string.Join("", arrSent).TrimEnd();
Console.WriteLine(finalSent);
}
}
}
And it breaks on this sentence:
Vazov received his elementary education in hisnative town of Sopoandat Plovdiv. The son of a conservative, well-to-do merchant.
20
1 6 17 2 5 0 15
Current Output:
ov eceived i e en ry educa i n hi ative to n of opo dat Plov iv. T e s of a co serva ive well-to- o mer ha t.
Intended Output:
ov eceived i e en ry educa i n hi ative to n of opo dat Plov iv. T e s of a co serva ive well-to- o mer han .
Soo it only doesn't work on the end.
Can someone help me?
Any suggestions?
Additional notes:
For example, we read the text "Well this problem is gonna be a ride." and line width 10. We distribute the text among 4 rows with 10 columns. We read the numbers "1 3 7 9" and drop bombs on those columns in the table.
The bombs destroy the character they fall on + all the neighbouring characters below it.
Note: Empty spaces below destroyed characters stop the bombs (see column 7).
Finally, we print the bombarded text on the console: "W l th s p o lem i o na be a r de."
Note: The empty cells in the table after the text should NOT be printed.
Your solution is very difficult to understand, keep it simple give names to the variables that you can understand easily.
I modified your code, hope it helps you:
static void Main()
{
string sentence = "Well this problem is gonna be a ride.";
int numberOfColumns = int.Parse("10");
List<int> bombs = "1 3 7 9".Split(' ').Select(int.Parse).ToList();
// we need to convert to decimal, otherwise C# will ignore decimal part.
//example: 127/20 = 6.35, so we need 7 rows. if we don't convert to decimal we have 6
// the Ceiling says, always round up. so even 6.1 will be rounded to 7
int numberOfRows = (int)Math.Ceiling(sentence.Length / Convert.ToDecimal(numberOfColumns));
char[,] array = new char[numberOfRows, numberOfColumns];
int sentencePointer = 0;
for (int rowIndex = 0; rowIndex < numberOfRows; rowIndex++)
{
for (int colIndex = 0; colIndex < numberOfColumns; colIndex++)
{
// if you want to print the grid with the full text, just comment the 3 lines below,
//and keep only "array[rowIndex, colIndex] = sentence[sentencePointer];"
if (bombs.Contains(colIndex))
{
if (sentence[sentencePointer] == ' ') // bomb is deactivated
{
bombs.Remove(colIndex);
array[rowIndex, colIndex] = sentence[sentencePointer];
}
else
array[rowIndex, colIndex] = '*'; // * represents a bomb
}
else
array[rowIndex, colIndex] = sentence[sentencePointer];
sentencePointer++; // move next character
if (sentencePointer >= sentence.Length)
break; // we reach the end of the sentence.
}
}
PrintGrid(array, numberOfRows, numberOfColumns);
// just give some space to print the final sentence
Console.WriteLine("");
Console.WriteLine("");
Console.WriteLine("");
for (int rowIndex = 0; rowIndex < numberOfRows; rowIndex++)
{
for (int colIndex = 0; colIndex < numberOfColumns; colIndex++)
{
Console.Write(array[rowIndex, colIndex]);
}
}
Console.ReadKey();
}
private static void PrintGrid(char[,] array, int numberOfRows, int numberOfColumns)
{
Console.WriteLine(new string('-', numberOfColumns * 2));
for (int rowIndex = 0; rowIndex < numberOfRows; rowIndex++)
{
Console.Write("|");
for (int colIndex = 0; colIndex < numberOfColumns; colIndex++)
{
Console.Write(array[rowIndex, colIndex]);
Console.Write("|");
}
Console.WriteLine("");
}
}
Somewhat more elegant solution.
private static IEnumerable<char> Bomb(IEnumerable<char> text, IEnumerable<int> indexes, int length)
{
var indexArray = new List<int>(indexes);
var used = new object[length];
return text.Select(
(c, index) =>
{
if (c != ' ' && indexArray.Contains(index % length))
{
used[index % length] = new object();
return '\0';
}
if (c == ' ' && used[index % length] != null)
{
indexArray.Remove(index % length);
}
return c;
});
}
OK so I have this function that works fine at inserting rows and then putting data within those rows.
public void inputRowData(string[] data, int rds)
{
int bestRow = getRowByRDS(rds);
string val = getValueOfCell(bestRow, 6);
if (val == null || val.Equals(""))
{
shiftRows(bestRow, data.Length-1);
string[] formatedData = formatOutput(bestRow, data);
// transform formated data into string[,]
string[][] splitedData = formatedData.Select(s => s.Split('\t')).ToArray();
var colCount = splitedData.Max(r => r.Length);
var excelData = new string[splitedData.Length, colCount];
for (int i = 0; i < splitedData.Length; i++)
{
for (int j = 0; j < splitedData[i].Length; j++)
{
excelData[i, j] = splitedData[i][j];
}
}
oSheet.get_Range("A" + bestRow.ToString()).Resize[splitedData.Length, colCount].Value = excelData;
}
else
{
Console.WriteLine("Line has some information already, skipping 1 more");
shiftRows(bestRow, data.Length + 1);
}
}
Now I if you take a look i find the "bestRow" which is determined by the last row in the excel with a int value at a particular column the code is show here:
private int getRowByRDS(int id)
{
int bestfit = -1;
Boolean foundOne = false;
Microsoft.Office.Interop.Excel.Range usedRange = oSheet.UsedRange;
for (int i = 2; i < usedRange.Rows.Count; i++)
{
string val = getValueOfCell(i, 3);
if (val == null)
continue;
int rds = int.Parse(val);
Console.WriteLine(val + " " +i);
if (rds == id)
{
bestfit = i;
foundOne = true;
}
else
if (foundOne)
return bestfit;
}
return bestfit;
}
What happens is that when it finishes on set of data in the inputRowData method it will move to another set with a different rds value. It will try to call getRowByRDS but it will throw an error.
On debug it looks like it didnt update the sheet... so lets say the first set of 10 strings was inserted at row 900, the and if the next set was suppose to start right after it bestRow will return 901 not 911.
The error is
A first chance exception of type 'System.Runtime.InteropServices.COMException' occurred in TTE Tool.exe
I found the problem. I disposed of the excel beforehand by mistake.