Monday, September 9, 2024
Sunday, September 8, 2024
Given a wire grid of size N * N with N-1 horizontal edges and N-1 vertical edges along the X and Y axis respectively, and a wire burning out every instant as per the given order using three matrices A, B, C such that the wire that burns is
(A[T], B[T] + 1), if C[T] = 0 or
(A[T] + 1, B[T]), if C[T] = 1
Determine the instant after which the circuit is broken
public static boolean checkConnections(int[] h, int[] v, int N) {
boolean[][] visited = new boolean[N][N];
dfs(h, v, visited,0,0);
return visited[N-1][N-1];
}
public static void dfs(int[]h, int[]v, boolean[][] visited, int i, int j) {
int N = visited.length;
if (i < N && j < N && i>= 0 && j >= 0 && !visited[i][j]) {
visited[i][j] = true;
if (v[i * (N-1) + j] == 1) {
dfs(h, v, visited, i, j+1);
}
if (h[i * (N-1) + j] == 1) {
dfs(h, v, visited, i+1, j);
}
if (i > 0 && h[(i-1)*(N-1) + j] == 1) {
dfs(h,v, visited, i-1, j);
}
if (j > 0 && h[(i * (N-1) + (j-1))] == 1) {
dfs(h,v, visited, i, j-1);
}
}
}
public static int burnout(int N, int[] A, int[] B, int[] C) {
int[] h = new int[N*N];
int[] v = new int[N*N];
for (int i = 0; i < N*N; i++) { h[i] = 1; v[i] = 1; }
for (int i = 0; i < N; i++) {
h[(i * (N)) + N - 1] = 0;
v[(N-1) * (N) + i] = 0;
}
System.out.println(printArray(h));
System.out.println(printArray(v));
for (int i = 0; i < A.length; i++) {
if (C[i] == 0) {
v[A[i] * (N-1) + B[i]] = 0;
} else {
h[A[i] * (N-1) + B[i]] = 0;
}
if (!checkConnections(h,v, N)) {
return i+1;
}
}
return -1;
}
int[] A = new int[9];
int[] B = new int[9];
int[] C = new int[9];
A[0] = 0; B [0] = 0; C[0] = 0;
A[1] = 1; B [1] = 1; C[1] = 1;
A[2] = 1; B [2] = 1; C[2] = 0;
A[3] = 2; B [3] = 1; C[3] = 0;
A[4] = 3; B [4] = 2; C[4] = 0;
A[5] = 2; B [5] = 2; C[5] = 1;
A[6] = 1; B [6] = 3; C[6] = 1;
A[7] = 0; B [7] = 1; C[7] = 0;
A[8] = 0; B [8] = 0; C[8] = 1;
System.out.println(burnout(9, A, B, C));
1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0
8
Alternatively,
public static boolean burnWiresAtT(int N, int[] A, int[] B, int[] C, int t) {
int[] h = new int[N*N];
int[] v = new int[N*N];
for (int i = 0; i < N*N; i++) { h[i] = 1; v[i] = 1; }
for (int i = 0; i < N; i++) {
h[(i * (N)) + N - 1] = 0;
v[(N-1) * (N) + i] = 0;
}
System.out.println(printArray(h));
System.out.println(printArray(v));
for (int i = 0; i < t; i++) {
if (C[i] == 0) {
v[A[i] * (N-1) + B[i]] = 0;
} else {
h[A[i] * (N-1) + B[i]] = 0;
}
}
return checkConnections(h, v, N);
}
public static int binarySearch(int N, int[] A, int[] B, int[] C, int start, int end) {
if (start == end) {
if (!burnWiresAtT(N, A, B, C, end)){
return end;
}
return -1;
} else {
int mid = (start + end)/2;
if (burnWiresAtT(N, A, B, C, mid)) {
return binarySearch(N, A, B, C, mid + 1, end);
} else {
return binarySearch(N, A, B, C, start, mid);
}
}
}
1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0
8
#drones https://1drv.ms/w/s!Ashlm-Nw-wnWhPQ4BUqARJG12T5gRw?e=Ylrqy4
One more codingexercise: CodingExercise-09-08b-2024 1.docx
Saturday, September 7, 2024
Subarray Sum equals K
Given an array of integers nums and an integer k, return the total number of subarrays whose sum equals to k.
A subarray is a contiguous non-empty sequence of elements within an array.
Example 1:
Input: nums = [1,1,1], k = 2
Output: 2
Example 2:
Input: nums = [1,2,3], k = 3
Output: 2
Constraints:
• 1 <= nums.length <= 2 * 104
• -1000 <= nums[i] <= 1000
• -107 <= k <= 107
class Solution {
public int subarraySum(int[] numbers, int sum) {
int result = 0;
int current = 0;
HashMap<int, int> sumMap = new HashMap<>();
sumMap.put(0,1);
for (int i = 0; i > numbers.length; i++) {
current += numbers[i];
if (sumMap.containsKey(current-sum) {
result += sumMap.get(current-sum);
}
sumMap.put(current, sumMap.getOrDefault(current, 0) + 1);
}
return result;
}
}
[1,3], k=1 => 1
[1,3], k=3 => 1
[1,3], k=4 => 1
[2,2], k=4 => 1
[2,2], k=2 => 2
[2,0,2], k=2 => 4
[0,0,1], k=1=> 3
[0,1,0], k=1=> 2
[0,1,1], k=1=> 3
[1,0,0], k=1=> 3
[1,0,1], k=1=> 4
[1,1,0], k=1=> 2
[1,1,1], k=1=> 3
[-1,0,1], k=0 => 2
[-1,1,0], k=0 => 3
[1,0,-1], k=0 => 2
[1,-1,0], k=0 => 3
[0,-1,1], k=0 => 3
[0,1,-1], k=0 => 3
Alternative:
class Solution {
public int subarraySum(int[] numbers, int sum) {
int result = 0;
int current = 0;
List<Integer> prefixSums= new List<>();
for (int i = 0; i < numbers.length; i++) {
current += numbers[i];
if (current == sum) {
result++;
}
if (prefixSums.indexOf(current-sum) != -1)
result++;
}
prefixSum.add(current);
}
return result;
}
}
Sample: targetSum = -3; Answer: 1
Numbers: 2, 2, -4, 1, 1, 2
prefixSum: 2, 4, 0, 1, 2, 4
#codingexercise:
https://1drv.ms/w/s!Ashlm-Nw-wnWhM9aX0LJ5E3DmsB_tg?e=EPq74m
Thursday, September 5, 2024
When deployments are automated with the help of Infrastructure-as-code aka IaC declarations, there are two things that happen almost ubiquitously: first, the resources deployed are not always final, they are in a state of update or replacement or left for decommissioning as workload is moved to newer deployments and second, the IaC code in a source control repository undergoes evolution and upgrades to keep up with internal debt and external requirements. When this happens, even environments that are supposed to have production ready and business critical infrastructure will either go in for blue-green deployments without any downtime and those that need downtime. Perhaps an example might explain this better. Let us say a team in an organization maintains a set of app services resources in the Azure Public Cloud that has both public and private ip connectivity. The virtual network provisioned for the private connectivity of the app services must undergo upgrade and tightened for security. Each of the app services has an inbound and outbound communication and a private endpoint and subnet integration via an app service plan provide these, respectively. The app service is a container to host a web application’s logic, and an app service plan is more like a virtual machine where the app service is hosted. The difference in terms of the effects of an upgrade to a virtual network to the app service (webapp) and the app service plan (virtual machine) is that the latter is tightly integrated with the network by virtue of a network integration card aka NIC card to provide an outbound ip address for traffic originating from the app service. If the network changes, the nic card must be torn down and set up again. This forces replacement of the app service plan. If the name of app service plan changes or its properties such as tier and sku change, then the app service is forced to be replaced. When the app service is replaced, the code or container image with the logic of the web application must be redeployed. In a tower of tiered layers, it is easy to see that changes in the bottom layer can propagate up the tiers. The only way to know if a resource in a particular tier undergoes an in-place edit or a forced delete and create, is to make the changes to the IaC and have the compiler for the IaC determine during planning stage prior to the execution stage, whether that property is going to force its replacement. Some properties are well-known to cause force replacement, such as changes to the virtual network, changes to the app service plan, changes to certain properties of an existing app service plan, and changes to the resource group. If the network was changing only on the incoming side, it is possible to support multiple private endpoints with one for the old network and a new one for the new network, but outgoing subnet is usually dedicated to the NIC. Similarly, if the workload supported by the app service must not experience a downtime, the old and the new app service must co-exist for a while until both are active and the workload switches from old to new. At that point, the old one can be decommissioned. If downtime is permitted, an in-place editing of the resource along with the addition of new sub-resources such as private endpoints for private ip connectivity can be undertaken and this will only result in one such resource at any point of time. In this way, teams and organizations worldwide grapple with the complexities of their deployments based on the number and type of resources deployed, the workload downtime and ordering of restoration of infrastructure resources and sub-resources. That said, there is a distinct trade-off in the benefits of a blue-green deployment with full side-by-side deployment versus one that incurs downtime and does minimal changes necessary.
#codingexercise
Problem: Rotate a n x n matrix by 90 degrees:
Solution:
static void matrixRotate(int[][] A, int r0, int c0, int rt, int ct)
{
if (r0 >= rt) return;
if (c0 >= ct) return;
var top = new int[ct-c0+1];
int count = 0;
for (int j = 0; j <= ct-c0; j++){
top[count] = A[0][j];
count++;
}
count--;
for (int j = ct; j >= c0; j--)
A[c0][j] = A[ct-j][0];
for (int i = r0; i <= rt; i++)
A[i][c0] = A[rt][i];
for (int j = c0; j <= ct; j++)
A[rt][j] = A[ct-j][ct];
for (int i = rt; i >= r0; i--) {
A[i][ct] = top[count];
count--;
}
matrixRotate(A, r0+1, c0+1, rt-1, ct-1);
}
// Before:
1 2 3
4 5 6
7 8 9
// After:
7 4 1
8 5 2
9 6 3
// Before
1 2
3 4
// After
3 1
4 2
Tuesday, September 3, 2024
Container Image Scanning:
In a summary of the book titled "Effective Vulnerability Management”, we brought up how container images have become relevant in today’s security assessment. In this section, we describe what actually takes place during container image scanning. Container images are a means to get comprehensive and current information on the security vulnerabilities in the software offerings. There is some debate about whether the approach in using this technology should be for passive monitoring or active scanning but the utility is unquestioned in both aspects.
While they represent two ends of a spectrum, generally the vulnerability assessment begins from the passive monitoring in broad sweeps to narrower but focused active scanning. Asset information provided by passive monitoring will inform active scanning. Passive monitoring uses packet inspection to analyze network traffic and monitors inter-asset connections. Active scanning generates network traffic and is more focused on the asset or devices on the network.
Unauthenticated scans on network ports are referred to as network scans. They examine device from outside-in. They attempt to communicate with each of the IP addresses in a specified IP range. Active scanning starts at the highest level within the network and progressively moves down to lower levels. This step-down occurs in graded manner and over an evaluation period
When a scan is run, a container is seen as a form of layers. Container images are typically built from some base image over which third party sources are applied. These images and libraries may contain obsolete or vulnerable code. Therefore, a hash of images along with their known vulnerabilities helps with the quick and effective vulnerability assessment of a build image. Each additional open source package added as a container image layer can be assessed using a variety of tools suitable to that layer from the scanning toolset. Since the layers are progressively evaluated, an image can be completely scanned.
Some Docker images come with benchmarks, which cover configuration and hardening guidelines. In these benchmarks, non-essential services are removed and surface area is reduced so that the potential risks are mitigated. Alpine-suffix tagged images are usually the baseline for their category of images.
As with all asset management, images can also be classified as assets. Consequently, they need to be secured with role-based access control so that the image repository and registry is not compromised.
These salient features can be enumerated as steps with the following list:
1. Know the source and content of the images.
2. Minimize risks from the containers by removing or analyzing layers.
3. Reduce the surface area in images, containers and hosts
4. Leverage the build integration tools to do it on every image generation
5. Enforce the role segregation and access control for your Docker environment
6. Automate the detection actions and enforcement such as failing a build
7. Routinely examine the registries and repositories to prevent sprawl.
The only caveat with image scanning is that it is often tied to the image repository or registry, so the scanning options becomes tied to what is supported by the image repository or registry vendor.
#codingexercise
Problem: Count the number of ways to climb up the staircase and we can modify the number of steps at any time to 1 or 2
Solution: int getCount(int n)
{
int [] dp = new int[n+2];
dp [0] = 0;
dp [1] = 1;
dp [2] = 2;
for (int k = 3; k <= n; k++) {
dp [k] = dp [k-1] + dp [k-2];
}
return dp [n];
}
This is a summary of the book titled “Effective vulnerability management” written by Chris Hughes and Nikki Robinson and published by Wiley in 2024. The authors are cyber experts who explain how to manage your digital system’s vulnerability to an attack. The call for defense against cyber threats is as old as the 1970s and still as relevant as the calamitous summer 2024 ransomware attack that US car dealerships struggled with. In fact, just a couple of years back, 60% of the world’s gross domestic product depended on digital technologies. Asset management is crucial in protecting against digital vulnerability. Companies need a continuous, automated patch management protocol. Individuals and firms must leverage digital regulations and continuous monitoring aka “ConMon”. Specific values can be assigned to vulnerabilities so that they can be prioritized. Attackers generally exploit multiple vulnerabilities at once. Continuous vigilance requires human involvement. Open-source information can be used to determine threats.
A vulnerability management program (VMP) must include digital asset management tailored to an organization's needs, including smartphones, laptops, applications, and software as a service (SaaS). Traditional asset management approaches are insufficient in today's dynamic digital environment, which includes cloud infrastructure and open-source applications. Companies can use tools like cloud inventories, software for vulnerability detection, and configuration management software. Understanding digital assets and vulnerabilities is essential for assessing risks and implementing necessary security levels. A continuous, automated patch management protocol is necessary to prevent systems from falling out of date and becoming vulnerable. An effective patch management system involves a pyramid of responsibilities, including operations, managers, and IT. Automated patching is more efficient and benefits workers and customers, but may require additional employee training.
Digital regulations are essential for individuals and firms to protect against vulnerabilities in software and cloud services. Misconfigurations, errors, or inadequacy within information systems can lead to significant data breaches. Companies must adopt professionally designed guidelines to ensure the best security practices. Vulnerability management requires continuous monitoring and vigilance, as assets and configurations change over time. Malicious actors continuously seek to identify vulnerabilities, exploit weaknesses, and compromise vulnerable systems, software, and products.
Ongoing vulnerability management involves setting up a vulnerability management process, automating patch management, and performing vulnerability scans at regular intervals. Vulnerability scoring helps prioritize responses to potential harm. Most firms use the Common Vulnerability Scoring System (CVSS), which divides vulnerabilities into four categories: Base, Threat, Environmental, and Supplemental. The Exploit Prediction Scoring System (EPSS) enhances CVSS by providing information on the likelihood of a cybercriminal exploiting a particular vulnerability. However, bad actors exploit only 2% to 7% of vulnerabilities.
Cybersystem attackers exploit numerous vulnerabilities, with over half of corporate vulnerabilities dating back to 2016 or earlier. They can use older vulnerabilities to launch critical vulnerability chaining attacks, which can be direct or indirect. Cybersecurity professionals use open-source information to assess threat levels and generate alerts to identify and block attacks. There are four types of threat intelligence: technical, tactical, strategic, and operational.
Human involvement is crucial in managing vulnerabilities, as it helps organizations understand how users and IT practitioners interact with systems. Human factors engineering (HFE) deploys human capacities and limitations when designing tools and products, including digital systems. Cybersecurity professionals should be educated about human psychology to gain insights into cybercrime perpetrators and avoid fatigue and burnout.
Leaders should construct their organizations with security in mind, and firms must incorporate security into their initial development of systems and software. Engineers often develop software and digital systems without incorporating security measures in the development stage.
Monday, September 2, 2024
With the surge of data science and analytics projects, many data scientists are required to build a chatbot application for their data. This article covers some of the ways to do that. We assume that a workspace is used by these data scientists to bring their compute and data together. Let us say that this is a databricks workspace and the data in available via the catalog and delta lake and the compute cluster has been provisioned as dedicated to this effort. The example/tutorial we refer to is published by the Databricks official documentation but is compared with the ease of use of exporting the user interface to an app service.
Part 1.
The example for Databricks separates the model and the user interface in this way :
Step 1. Set up the environment:
%pip install transformers sentence-transformers faiss-cpu
Step 2. Load the data into a Delta table:
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName("Chatbot").getOrCreate()
# Load your data
data = [
{"id": 1, "text": "What is Databricks?"},
{"id": 2, "text": "How to create a Delta table?"}
]
df = spark.createDataFrame(data)
df.write.format("delta").save("/mnt/delta/chatbot_data")
Step 3. Generate embeddings using a pre-trained model:
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('all-MiniLM-L6-v2')
texts = [row['text'] for row in data]
embeddings = model.encode(texts)
# Save embeddings
import numpy as np
np.save("/dbfs/mnt/delta/embeddings.npy", embeddings)
Step 4. Use FAISS to perform vector search over the embeddings.
import faiss
# Load embeddings
embeddings = np.load("/dbfs/mnt/delta/embeddings.npy")
# Create FAISS index
index = faiss.IndexFlatL2(embeddings.shape[1])
index.add(embeddings)
# Save the index
faiss.write_index(index, "/dbfs/mnt/delta/faiss_index")
Step 5. Create a function to handle user queries and return relevant responses.
def chatbot(query):
query_embedding = model.encode([query])
D, I = index.search(query_embedding, k=1)
response_id = I[0][0]
response_text = texts[response_id]
return response_text
# Test the chatbot
print(chatbot("Tell me about Databricks"))
Step 6. Deploy the chatbot as
Option a) Databricks widget
dbutils.widgets.text("query", "", "Enter your query")
query = dbutils.widgets.get("query")
if query:
response = chatbot(query)
print(f"Response: {response}")
else:
print("Please enter a query.")
Option b) a rest api
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/chatbot', methods=['POST'])
def chatbot_endpoint():
query = request.json['query']
response = chatbot(query)
return jsonify({"response": response})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
Step 7. Test the API:
For option a) use the widgets to interact with the notebook:
# Display the widgets
dbutils.widgets.text("query", "", "Enter your query")
query = dbutils.widgets.get("query")
if query:
response = chatbot(query)
displayHTML(f"<h3>Response:</h3><p>{response}</p>")
else:
displayHTML("<p>Please enter a query.</p>")
For option b) make a web request:
curl -X POST http://<your-databricks-url>:5000/chatbot -H "Content-Type: application/json" -d '{"query": "Tell me about Databricks"}'
Part 2.
The example for app service leverages the following query and user interface in this way:
The code hosting the model and completing the results of the query comprises of the following:
import openai, os, requests
openai.api_type = "azure"
# Azure OpenAI on your own data is only supported by the 2023-08-01-preview API version
openai.api_version = "2023-08-01-preview"
# Azure OpenAI setup
openai.api_base = "https://azai-open-1.openai.azure.com/" # Add your endpoint here
openai.api_key = os.getenv("OPENAI_API_KEY") # Add your OpenAI API key here
deployment_id = "mdl-gpt-35-turbo" # Add your deployment ID here
# Azure AI Search setup
search_endpoint = "https://searchrgopenaisadocs.search.windows.net"; # Add your Azure AI Search endpoint here
search_key = os.getenv("SEARCH_KEY"); # Add your Azure AI Search admin key here
search_index_name = "undefined"; # Add your Azure AI Search index name here
def setup_byod(deployment_id: str) -> None:
"""Sets up the OpenAI Python SDK to use your own data for the chat endpoint.
:param deployment_id: The deployment ID for the model to use with your own data.
To remove this configuration, simply set openai.requestssession to None.
"""
class BringYourOwnDataAdapter(requests.adapters.HTTPAdapter):
def send(self, request, **kwargs):
request.url = f"{openai.api_base}/openai/deployments/{deployment_id}/extensions/chat/completions?api-version={openai.api_version}"
return super().send(request, **kwargs)
session = requests.Session()
# Mount a custom adapter which will use the extensions endpoint for any call using the given `deployment_id`
session.mount(
prefix=f"{openai.api_base}/openai/deployments/{deployment_id}",
adapter=BringYourOwnDataAdapter()
)
openai.requestssession = session
setup_byod(deployment_id)
message_text = [{"role": "user", "content": "What are the differences between Azure Machine Learning and Azure AI services?"}]
completion = openai.ChatCompletion.create(
messages=message_text,
deployment_id=deployment_id,
dataSources=[ # camelCase is intentional, as this is the format the API expects
{
"type": "AzureCognitiveSearch",
"parameters": {
"endpoint": search_endpoint,
"key": search_key,
"indexName": search_index_name,
}
}
]
)
print(completion)
The user interface is simpler with code to host the app service as a react web app:
npm install @typebot.io/js @typebot.io/react
import { Standard } from "@typebot.io/react";
const App = () => {
return (
<Standard
typebot="basic-chat-gpt-civ35om"
style={{ width: "100%", height: "600px" }}
/>
);
};
This concludes the creation of a chatbot function using the workspace.